The DOM Component Manifesto

The DOM Component Manifesto

Embracing standards is better than chasing frameworks

by Joe Honton

It seems like every time a developer discovers a good coding pattern, they want to turn it into a framework. Good for them. They’ve found something that works and want to share it with others. But I’ve found something that works for me, and you probably have too. So we don’t need their framework because it solves their problem — not ours.

Instead, what we need is simply a consistent way to produce good results.

So, for consistency, I’ve chosen to follow a standard pattern for all of the DOM components I’ve built in order to achieve those good results. While it’s tempting to turn this pattern into a framework, I’ve intentionally resisted that urge. That turned out to be a good decision.

Yes, each DOM component has the same initialization pattern, the same reliance on event-based communication, and many of the same function names. But that’s where the pattern ends and the unique aspects of the component begin. Instead of fighting a framework, writing code whose only purpose is to get around some unaccounted-for limitation, developers should be given the freedom to adapt my pattern — or your pattern — in any way that makes sense.

So for me, frameworks are out and patterns are in. But which pattern?

The answer is all around us. It is simply to embrace the languages, protocols, and open standards that have been developed and freely given to us, laid before us like gleaming treasure.

My philosophy for DOM components is to embrace the standards developed by the World Wide Web Consortium (W3C), Ecma International, and the Internet Engineering Task Force (IETF). These are the deliberative bodies that have worked so hard to give us a way to mark up, style, script, and deliver a great web experience across a diverse set of hardware devices.

This five-part philosophy embraces isolation, separation, modularization, configuration, and best practices.


Isolation — DOM component’s raison d’être. This is where shadow DOM fits in. It establishes a firewall between the host document and the component instance. One can’t affect the other. Plus, an all-important corollary to this is that my component can’t cause your component to fail.

Isolation also means that each instance of a defined component gets its own namespace. Thus, element identifiers and CSS class names can be simple and to the point, without prefixes or instance qualifiers.

An identifier like #xyzFrame001 could be shortened to just #frame. Even better, a CSS selector for anchor elements, like a.specialLink {...}, might be reduced to just a {...}, completely eliminating the need for class names in many cases.

Most importantly, isolation eliminates a wide range of hard-to-track-down bugs that promiscuous CSS seems to propagate with such ease.


Separation — as in the separation of concerns. This is one of the most important software development mantras of the past two decades. It’s helped us to achieve the level of success we now have. The former use of all-in-one languages has declined over the years, while the use of separate languages for markup, styling, and scripting has risen. Sadly, some brand-new frameworks seem to have forgotten this golden rule.

In order to get the benefit of great tooling, like syntax highlighting, linting, inspecting, profiling, and compliance checking, the code we write should place each language in its own file.

The hidden bonus to this approach is caching. HTML templates are loaded once and cached by the browser, CSS declarations are loaded once and cached by the browser, JavaScript modules are loaded once and cached by the browser — all automatically, without any effort on our part.


Modularization — the Holy Grail. JavaScript has finally grown up and given us a good way to keep variables out of global scope. Every major browser now supports ESNext modules, so now is the time to embrace the simplicity and safety of modules.

Significantly, this means no transpilation or shims, no manifest or packaging overhead, and no bundlers or splitters or loaders. It means we can simply write our scripts and deploy them directly to the server. We can rediscover the fun of interpreted JavaScript.

And because browsers load scripts only when needed, we don’t have to do anything special to gain the benefits of just-in-time, on-demand loading.


Customization — usage in alternate settings. Components should be designed to accommodate distinctly different values. And components should allow consumers to apply their own decorative branding to their visual interface.

DOM standards give us three ways to expose this customization to our component consumers: with slotted elements, with HTML attributes, and with CSS variables. These are native to the HTML and CSS languages, so they use the same syntax and follow the same idiomatic expressions as everything we’ve already learned. Unlike props, they look and feel like the real thing because they are.


Best Practices — guidelines and guardrails that make everything better. Remember, our collective success is the result of hard-fought battles. Best practices are simply a distillation of all the strategies and safety rules that helped us to win those battles. Here’s what works for DOM components:

  • Use a modern HTTP/2 server to eliminate latency and move component files from server to browser in one continuous session.
  • Migrate away from legacy transpiler/bundler/splitter/loader lifecycles. Adopt the newer ESNext approach to asynchronous, modular, cacheable delivery.
  • Come to terms with the reality that browser scripting is based on an object model. Use classes and object instances in your scripts. After all, the entire DOM is proof that object-oriented programming works.
  • Stop chasing undefined errors. Replace anonymous objects with declared classes that have well-defined shapes and proper constructor initialization.
  • Use events instead of callbacks. Remember that the biggest breakthrough of the 1980s was event-driven programming. It’s what enables all our mouse and windows behavior. It’s the original non-blocking coding pattern.

Conclusion

The catalysts for this manifesto are these open source DOM components. For a more in-depth exploration of the philosophy behind it, see The 7 Facets of Web Components.

That’s my manifesto. Five clear ideas that solve all of my DOM component problems. No more semiannual overhauls to upgrade to the latest breaking-change framework. No more chasing after shiny new things. All standards-based. All future-proofed.

The DOM Component Manifesto — Embracing standards is better than chasing frameworks

🔎