Using <custom-elements> in production (2016)
JavaScript HTML CSS
Latest commit dc53226 Aug 8, 2016 @thomaswilburn Defer work to connectedCallback
The V1 spec says that elements cannot create or access attributes from
the constructor, so let's move this all to the connection even (with a
guard to keep upgrades from happening twice).



Although this is a presentation on using custom elements in production, it's also a demonstration of how to build custom elements that will work across V0, V1, and both major polyfills. The scripts above define three elements (<slide-show>, <text-slide>, and <code-slide>) and demonstrates their use in a UI script.

In addition to demonstrating the technical process of registration, these elements follow what I think are minimum best-practices, as detailed below. You may also be interested in the "gold standard" published by for component authors.

Asynchronous parent/child upgrade

During startup, parents should not assume that their children upgrade before they do. Children shouldn't assume that their parents have already been resolved. Elements also shouldn't assume that they have any attributes or children at startup.

In practice, this means your element should be fine starting from a blank/empty state, and should watch its own contents and attributes for changes in order to react. It's also good for elements to use getter/setter properties instead of methods for reflecting state, with those properties reflected in attributes where possible.

Notify via DOM events, not promises

Built-in elements have two primary ways of communicating with outside clients: events and getter/setter properties. Try to stick to these when implementing your own elements, in order to blend in more seamlessly. Promises are not recommended as a way to check element state: unresolved tags won't have the promise as a property yet, requiring extra null checks from your users. Instead, fire a custom event when state changes, including element upgrade, and let external scripts subscribe to know when they should react.

Batch rendering

Your component may be asked to render multiple times per JS event loop, especially when large numbers of child elements are upgrading asynchronously. As a rule of thumb, batch rendering up and defer to the next frame if the update was triggered by an event. However, when reacting to attribute or content changes, you may want to render immediately if the user would expect the document to reflow as a result.

Take least responsibility seriously

Whenever possible, write elements to handle small, self-contained bits of functionality. Like UNIX tools, a tag should do one thing well. It's also better to be able to compose multiple elements together than it is to have one mega-element with all the code inside of it.