Today at Red Hat is day of learning again!
I used the occasion to brush up my knowledge about web components and taking a look
at PatternFly Elements. I’ve leered at that
for a long time already – using “regular” PatternFly
requires React, and thus all the npm
, bundler, build system etc. baggage
around it.
In Cockpit we support
writing your own plugins
with a simple static .html
and .js
file, and how cool would it be to
let them have the usual PatternFly look to blend in with all the other pages?
Also, these days the web platform really supports all the concepts that React
introduces, which means there’s a lot less code to load into the browser if you
just use plain web components.
They may not be very visible and some may even declare them “dead”, but they very much aren’t. 😀
Static webpage with PatternFly Elements
I started with updating my old
PatternFly CDN demo
(source)
to the current version 4. That now requires using an import map,
which were entirely new to me. With them you can use the usual import
"@namespace/module"
on your page without using a bundler – how amazing! This
CDN model is completely fine for a quick-and-dirty webpage with minimal effort.
A self-contained version of that uses local npm modules. I made a
demo for
that as well – you need to check it out, run npm install
, then start a
web server on it (npm run-script run
will use Python’s http.server
), and
look at it on http://localhost:8080 (file://
does not work in that situation).
Cockpit starter-kit
starter-kit is a demo extension for Cockpit that gives you a ready-to-run project with all the bells and whistles: npm modules, build system, translations, linting, and browser integration tests on a dozen OSes and multiple browsers. Like every other official Cockpit page this also uses PatternFly 5 and React.
I created a starter-kit branch/PR that uses PatternFly Elements and Lit instead, which was pleasantly straightforward. The size reduction is quite impressive:
index.js.gz
shrinks from 80 kB to 29 kB. This includes the PatternFly CSS!index.css.gz
, which was previously 23 kBytes, disappears entirely.node_modules
shrinks from 381 MB to 202 MB.
My main trouble was with the tests: they were broken because the standard document.querySelectorAll()
cannot pierce through shadow DOMs (and is not supposed to). The top-level DOM is now just a single <ct-application />
tag, which of course contains a lot more shadow DOMs for each PF element.
After some research I picked the query-selector-shadow-dom NPM module
which provides a convenient querySelectorAllDeep()
API that makes shadow DOM
pretty much transparent. I.e. tests don’t have to know/specify at which point
the shadow DOM boundaries are in a selector. I sent
PR#21233 to teach our testlib
about it.
With that, my starter-kit PFE branch works end-to-end, including running the tests locally and in our CI. They still fail on the Testing Farm for some subtle reason, I’ll investigate that next week.
PatternFly Elements development
After that I turned my attention to the patternfly-elements
project itself. I worked
through the development setup,
played around with the dev server, tests, demos, and adding a new example
component. During that I noticed that npm new
generates a broken template with two
TypeScript errors. I reported a bug
about that and sent PR#2873
to fix it.
The main thing that holds us back is that there are still a lot of components missing compared to PatternFly React, such as Alert, Checkbox, or TimePicker.
For the missing Alert there is already an upstream issue and an old PR. I dusted this off, cleaned it up, and worked on that for about two hours until everything built and the demos worked. However, there’s still a lot more to be done before it’s ready for a PR. For the time being I pushed it to my fork.