Post contents
Web components enjoy large-scale usage today. From YouTube to GitHub and many other major organizations, it’s safe to say they’ve made their way into commonplace frontend development practices.
That wasn’t always the case. After all, web components had to start somewhere. And web development can be particularly picky with what succeeds and what doesn’t.
So then, how did web components succeed? What was their path to broad adoption? And what are the origins behind the APIs used for modern web components?
Let’s walk through a short history of web components and the related ecosystem to answer these questions.
2010: The Early Days of MVC in JS
While the concept of “Model View Controller”, also commonly called MVC, has been around for some time, in JavaScript itself it failed to take hold early on.
However, in 2010, there was an explosion around MVC and it’s related cousin: Model View View-Controller (MVVC) ). This explosion came courtesy of a slew of new frameworks that launched only a few months apart from one-another.
Knockout was one of the first to introduce strict MVC patterns inside of JavaScript in July 2010. Knockout supported observable-based UI binding. Here, you could declare a Model, and bind data from said model directly to your HTML.
<!-- Demo of KnockoutJS --><table class="mails" data-bind="with: chosenFolderData"> <thead><tr><th>Subject</th></tr></thead> <tbody data-bind="foreach: mails"> <tr><td data-bind="text: subject"></td></tr> </tbody></table><script>function WebmailViewModel() { // Data var self = this; self.chosenFolderData = ko.observable(); $.get('/mail', { folder: 'Inbox'}, self.chosenFolderData)};ko.applyBindings(new WebmailViewModel());</script>
While this works great for UI binding, it lacks the componentization aspect we’ve come to expect from modern frameworks.
This was improved in the ecosystem when Backbone saw its first release in October 2010. It introduced a [View](https://backbonejs.org/#View-extend)
, similar to what we might expect a component to be like today.
var DocumentRow = Backbone.View.extend({ tagName: "li", className: "document-row", events: { "click .icon": "open", "click .button.edit": "openEditDialog", "click .button.delete": "destroy" }, initialize: function() { this.listenTo(this.model, "change", this.render); }, render: function() { ... }});
Here, we can see that we can now bind events, classes, and more to a single tag. This aligns better with the types of components we’d see in, say, React or Lit.
But that’s not all we saw in October that year. We also saw the initial release of Angular.js only 10 days after Backbone’s release.
Here, we can see that it introduced a concept of controllers into the document, similar to the Model
s of Knockout. It allowed two-way bindings from UI to data and back.
<div ng-controller="TodoListController as todoList"> <ul> <li ng-repeat="todo in todoList.todos">{{todo.text}}</li> </ul> <form ng-submit="todoList.addTodo()"> <input type="text" ng-model="todoList.todoText" /> <input class="btn-primary" type="submit" value="add" /> </form></div><script> angular .module("todoApp", []) .controller("TodoListController", function () { var todoList = this; todoList.todos = [ { text: "learn AngularJS" }, { text: "build an AngularJS app" }, ]; todoList.addTodo = function () { todoList.todos.push({ text: todoList.todoText }); todoList.todoText = ""; }; });</script>
While Angular was the last of the three mentioned here, it had a huge impact. It was the first time Google released a JavaScript-based MVC based library into the wild.
Not only did they build the library, they used it to build Google’s Feedback tool - which powers almost all of Google’s products today. This represented a shift from their prior Java-based “Google Web Toolkit” (GWT) that was widely used before.
Later, with the acquisition of DoubleClick, the team that was working on the migration of the DoubleClick platform for Google decided to use Angular.js as well.
2011: A Glimmer in W3C Standard’s Eye
With Angular.js continuing to grow within Google, it’s no surprise that they continued researching in-JavaScript HTML bindings.
On this topic, Alex Russel - then a Senior Staff Engineer at Google, working on the web platform team - gave a talk at the Fronteers conference.
In this talk, he introduces a host of libraries that allow building custom elements with experimental new APIs.
<script>class Comment extends HTMLElement { constructor(attrs = {}) { super(attrs); this.textContent = attrs.text || lorem; this.shadow = new ShadowRoot(this); this.buildUI(); } buildUI() { ... }}HTMLElement.register('x-comment', Comment);var c = new Comment("Howdy, pardner!");document.body.appendChild(c);</script><x-comment>...</x-comment>
Here, he utilized the TraceUR compiler (a precursor to Babel) to add classes (remember, class
wouldn’t land in JavaScript stable until ES6 in 2015) to build a new “custom element”.
This combined with their new MDV library in order to create a similar development environment to what we have in browser APIs today.
It’s important to note that at this stage, nothing was formalized inside of a specification - It was all experimental libraries acting as playgrounds for APIs.
That would change soon after.
2013: Things Start Heating Up
In early 2013 the Google team created a Working Draft of a specification for Custom Elements. Alongside similar working drafts for Shadow DOM APIs, they were colloquially called “Custom Elements v0”.
With Google Chrome’s release in 2008, they had the ability to quickly implement these non-standard APIs into Chrome in order to allow application developers to utilize them before specification stabilization.
One such example of this was Polymer, which was a component library based on v0 APIs to provide two-way UI binding using MVC. It’s initial alpha release was announced in early 2013, alongside the specifications.
At Google Dev Summit 2013, they walked through its capabilities and how it was able to run in other browsers by utilizing polyfills.
Facebook, not one to be outdone on the technical engineering front, introduced React into public in 2013
While Polymer went deeper into the MVC route, React relied more heavily on unidirectionality in order to avoid state mutations.
2016 & 2017: Formative Years
While only the year prior, Polymer 1.0 was released with the usage of v0 custom element spec, 2016 saw the release of the custom element v1 specification.
This new version of the specification was not backwards compatible, and as a result required a shift to the new version of the specification in order to function properly. Polyfills were continued to be used as a stop-gate for browsers that didn’t have a v0 implementation.
While v1 was already implemented into Chrome in late 2016, it wasn’t until 2017 with the release of Polymer 2.0 that it would be adopted back into the library that helped draft the specification.
Because of this, while YouTube’s new Polymer rewrite theoretically was a huge step towards the usage of web components, it posed a problem. Browsers like Firefox without a v0 implementation were forced to continue to use Polyfills, which are slower than native implementations.
2018 and Beyond: Maturity
2018 is where Web Components really found their foothold.
For a start, Mozilla implemented the v1 specification APIs into their stable release of Firefox, complete with dedicated devtools. Finally, developers could use all of the web components’ APIs in their app, cross-browser, and without any concern for non-Chrome performance.
On top of that, React’s unidirectionality seemed to have won over the Polymer team. The Polymer team announced that it would migrate away from bidirectional binding and towards a one-way bound LitElement
That LitElement
would then turn into a dedicated framework called “Lit”, developed to replace Polymer as its successor, that would hit v1 in 2019 and v2 in 2021.
Timeline
Whew! That’s a lot to take in. Let’s see it all from a thousand foot view:
-
2010:
-
2011:
-
2013:
-
2015:
-
2016:
-
2017:
-
2018:
-
2019:
-
2021
Conclusion
In the past 10 years we’ve seen massive changes to the web development ecosystem. No more is this more apparent than the development and continued growth of web components.
Hopefully this should put any future learnings about web components and framework comparisons into perspective.
We’ve waited a long time to see many of these ideas fully standardized into the web platform, and, now that they’re here, they’re helping accelerate growth of many platforms.
Want to learn how to build them yourself?
We have articles about how to build web components without a framework as well as using Google’s Lit framework.