{"id":3730,"date":"2021-12-21T13:40:37","date_gmt":"2021-12-21T21:40:37","guid":{"rendered":"https:\/\/coderpad.io\/?p=3730"},"modified":"2023-06-05T14:37:51","modified_gmt":"2023-06-05T21:37:51","slug":"web-components-101-history","status":"publish","type":"post","link":"https:\/\/coderpad.io\/blog\/development\/web-components-101-history\/","title":{"rendered":"Web Components 101: History"},"content":{"rendered":"<p>Web components enjoy large-scale usage today. From YouTube to GitHub and many other major organizations, it\u2019s safe to say they\u2019ve made their way into commonplace frontend development practices.&nbsp;<\/p>\n\n<p>That wasn\u2019t always the case. After all, web components had to start somewhere. And web development can be particularly picky with what succeeds and what doesn\u2019t.<\/p>\n\n<p>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?<\/p>\n\n<p>Let\u2019s walk through a short history of web components and the related ecosystem to answer these questions.<\/p>\n\n<aside class=\"\n    cta-banner\n     cta-banner--bg-blue      cta-banner--has-media \"\ndata-block-name=\"cta-banner\">\n    <div class=\"inner\">\n        <div class=\"content\">\n                            <h2 class=\"headline\">Learn how to run front-end developer interviews that don&#8217;t suck<\/h2>\n            \n                            <div class=\"cta-buttons\">\n                                    <a href=\"https:\/\/coderpad.io\/blog\/interviewing\/5-tips-for-interviewing-frontend\/\" class=\"button  js-cta--read-our-guide\"  data-ga-category=\"CTA\" data-ga-label=\"Learn how to run front-end developer interviews that don&#039;t suck|Read our guide\">Read our guide<\/a>\n                                <\/div>\n                    <\/div>\n                    <div class=\"media\">\n                <img loading=\"lazy\" decoding=\"async\" width=\"432\" height=\"342\" src=\"https:\/\/coderpad.io\/wp-content\/uploads\/2022\/08\/Illustration-of-man-with-beard-popping-out-of-computer-chat.png\" class=\"attachment-large size-large\" alt=\"\" srcset=\"https:\/\/coderpad.io\/wp-content\/uploads\/2022\/08\/Illustration-of-man-with-beard-popping-out-of-computer-chat.png 432w, https:\/\/coderpad.io\/wp-content\/uploads\/2022\/08\/Illustration-of-man-with-beard-popping-out-of-computer-chat-300x238.png 300w\" sizes=\"auto, (max-width: 432px) 100vw, 432px\" \/>\n            <\/div>\n            <\/div>\n<\/aside>\n\n\n<h1 class=\"wp-block-heading\">2010: The Early Days of MVC in JS<\/h1>\n\n\n<p>While the concept of <a href=\"https:\/\/en.wikipedia.org\/wiki\/Model%E2%80%93view%E2%80%93controller\" target=\"_blank\" rel=\"noopener\">\u201cModel View Controller\u201d, also commonly called MVC<\/a>, has been around for some time, in JavaScript itself it failed to take hold early on.<\/p>\n\n\n<p>However, in 2010, there was an explosion around MVC and it\u2019s 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.<\/p>\n\n\n<p><a href=\"https:\/\/github.com\/knockout\/knockout\/releases\/tag\/v1.0.0\" target=\"_blank\" rel=\"noopener\">Knockout was one of the first to introduce strict MVC patterns inside of JavaScript in July 2010<\/a>. Knockout supported observable-based UI binding. Here, you could declare a Model, and bind data from said model directly to your HTML.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\">\n<span class=\"hljs-comment\">&lt;!-- Demo of KnockoutJS --&gt;<\/span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">table<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"mails\"<\/span> <span class=\"hljs-attr\">data-bind<\/span>=<span class=\"hljs-string\">\"with: chosenFolderData\"<\/span>&gt;<\/span>\n\u00a0 \u00a0 <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">thead<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">tr<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">th<\/span>&gt;<\/span>Subject<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">th<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">tr<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">thead<\/span>&gt;<\/span>\n\u00a0 \u00a0 <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">tbody<\/span> <span class=\"hljs-attr\">data-bind<\/span>=<span class=\"hljs-string\">\"foreach: mails\"<\/span>&gt;<\/span>\n\u00a0 \u00a0 \u00a0 \u00a0 <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">tr<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">td<\/span> <span class=\"hljs-attr\">data-bind<\/span>=<span class=\"hljs-string\">\"text: subject\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">td<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">tr<\/span>&gt;<\/span>\n\u00a0 \u00a0 <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">tbody<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">table<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">script<\/span>&gt;<\/span><span class=\"javascript\">\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">WebmailViewModel<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n\u00a0 \u00a0 <span class=\"hljs-comment\">\/\/ Data<\/span>\n\u00a0 \u00a0 <span class=\"hljs-keyword\">var<\/span> self = <span class=\"hljs-keyword\">this<\/span>;\n\u00a0 \u00a0 self.chosenFolderData = ko.observable();\n\n\u00a0 \u00a0 $.<span class=\"hljs-keyword\">get<\/span>('\/mail', { folder: <span class=\"hljs-string\">'Inbox'<\/span>}, self.chosenFolderData)\n};\n\nko.applyBindings(<span class=\"hljs-keyword\">new<\/span> WebmailViewModel());\n<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">script<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/coderpad.io\/wp-content\/uploads\/2021\/12\/img_61c249d556901.png\" alt=\"\"\/><\/figure>\n\n\n<p>While this works great for UI binding, it lacks the componentization aspect we\u2019ve come to expect from modern frameworks.<\/p>\n\n\n<hr class=\"wp-block-separator has-css-opacity\"\/>\n\n\n\n<p>This was improved in the ecosystem when <a href=\"https:\/\/github.com\/jashkenas\/backbone\/releases\/tag\/0.1.0\" target=\"_blank\" rel=\"noopener\">Backbone saw its first release in October 2010<\/a>. It introduced a `<a href=\"https:\/\/backbonejs.org\/#View-extend\" target=\"_blank\" rel=\"noopener\">View<\/a>`, similar to what we might expect a component to be like today.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">\n<span class=\"hljs-keyword\">var<\/span> DocumentRow = Backbone.View.extend({\n\u00a0 <span class=\"hljs-attr\">tagName<\/span>: <span class=\"hljs-string\">\"li\"<\/span>,\n\u00a0 <span class=\"hljs-attr\">className<\/span>: <span class=\"hljs-string\">\"document-row\"<\/span>,\n\u00a0 <span class=\"hljs-attr\">events<\/span>: {\n\u00a0 \u00a0 <span class=\"hljs-string\">\"click .icon\"<\/span>:\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span class=\"hljs-string\">\"open\"<\/span>,\n\u00a0 \u00a0 <span class=\"hljs-string\">\"click .button.edit\"<\/span>: \u00a0 <span class=\"hljs-string\">\"openEditDialog\"<\/span>,\n\u00a0 \u00a0 <span class=\"hljs-string\">\"click .button.delete\"<\/span>: <span class=\"hljs-string\">\"destroy\"<\/span>\n\u00a0 },\n\u00a0 <span class=\"hljs-attr\">initialize<\/span>: <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n\u00a0 \u00a0 <span class=\"hljs-keyword\">this<\/span>.listenTo(<span class=\"hljs-keyword\">this<\/span>.model, <span class=\"hljs-string\">\"change\"<\/span>, <span class=\"hljs-keyword\">this<\/span>.render);\n\u00a0 },\n\u00a0 <span class=\"hljs-attr\">render<\/span>: <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n\u00a0 \u00a0 ...\n\u00a0 }\n});<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n<p>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\u2019d see in, say, React or Lit.<\/p>\n\n\n<hr class=\"wp-block-separator has-css-opacity\"\/>\n\n\n\n<p>But that\u2019s not all we saw in October that year. We also saw the <a href=\"https:\/\/github.com\/angular\/angular.js\/releases\/tag\/v0.9.0\" target=\"_blank\" rel=\"noopener\">initial release of Angular.js<\/a> only 10 days after Backbone\u2019s release.<\/p>\n\n\n<p>Here, we can see that it introduced a concept of controllers into the document, similar to the <code>Model<\/code>s of Knockout. It allowed two-way bindings from UI to data and back.<\/p>\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\">\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">ng-controller<\/span>=<span class=\"hljs-string\">\"TodoListController as todoList\"<\/span>&gt;<\/span>\n\u00a0 <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ul<\/span>&gt;<\/span>\n\u00a0 \u00a0 <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">li<\/span> <span class=\"hljs-attr\">ng-repeat<\/span>=<span class=\"hljs-string\">\"todo in todoList.todos\"<\/span>&gt;<\/span>{{todo.text}}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">li<\/span>&gt;<\/span>\n\u00a0 <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">ul<\/span>&gt;<\/span>\n\u00a0 <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">form<\/span> <span class=\"hljs-attr\">ng-submit<\/span>=<span class=\"hljs-string\">\"todoList.addTodo()\"<\/span>&gt;<\/span>\n\u00a0 \u00a0 <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">input<\/span>\n\u00a0 \u00a0 \u00a0 <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"text\"<\/span>\n\u00a0 \u00a0 \u00a0 <span class=\"hljs-attr\">ng-model<\/span>=<span class=\"hljs-string\">\"todoList.todoText\"<\/span>\n\u00a0 \u00a0 \/&gt;<\/span>\n\u00a0 \u00a0 <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">input<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"btn-primary\"<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"submit\"<\/span> <span class=\"hljs-attr\">value<\/span>=<span class=\"hljs-string\">\"add\"<\/span> \/&gt;<\/span>\n\u00a0 <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">form<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">script<\/span>&gt;<\/span><span class=\"actionscript\">\n\u00a0 angular\n\u00a0 \u00a0 .module(<span class=\"hljs-string\">\"todoApp\"<\/span>, &#91;])\n\u00a0 \u00a0 .controller(<span class=\"hljs-string\">\"TodoListController\"<\/span>, <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-params\">()<\/span> <\/span>{\n\u00a0 \u00a0 \u00a0 <span class=\"hljs-keyword\">var<\/span> todoList = <span class=\"hljs-keyword\">this<\/span>;\n\u00a0 \u00a0 \u00a0 todoList.todos = &#91;\n\u00a0 \u00a0 \u00a0 \u00a0 { text: <span class=\"hljs-string\">\"learn AngularJS\"<\/span> },\n\u00a0 \u00a0 \u00a0 \u00a0 { text: <span class=\"hljs-string\">\"build an AngularJS app\"<\/span> },\n\u00a0 \u00a0 \u00a0 ];\n\n\u00a0 \u00a0 \u00a0 todoList.addTodo = <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-params\">()<\/span> <\/span>{\n\u00a0 \u00a0 \u00a0 \u00a0 todoList.todos.push({ text: todoList.todoText });\n\u00a0 \u00a0 \u00a0 \u00a0 todoList.todoText = <span class=\"hljs-string\">\"\"<\/span>;\n\u00a0 \u00a0 \u00a0 };\n\u00a0 \u00a0 });\n<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">script<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n<p>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.<\/p>\n\n\n<p>Not only did they build the library, <a href=\"https:\/\/www.youtube.com\/watch?v=r1A1VR0ibIQ\" target=\"_blank\" rel=\"noopener\">they used it to build Google\u2019s Feedback tool<\/a> &#8211; which powers almost all of Google\u2019s products today. This represented a shift from their prior Java-based \u201c<a href=\"http:\/\/www.gwtproject.org\/\" target=\"_blank\" rel=\"noopener\">Google Web Toolkit\u201d (GWT)<\/a> that was widely used before.<\/p>\n\n\n\n<p>Later, with the <a href=\"https:\/\/www.nytimes.com\/2007\/04\/14\/technology\/14DoubleClick.html\" target=\"_blank\" rel=\"noopener\">acquisition of DoubleClick<\/a>, the team that was working on the <a href=\"https:\/\/www.youtube.com\/watch?v=r1A1VR0ibIQ\" target=\"_blank\" rel=\"noopener\">migration of the DoubleClick platform for Google decided to use Angular.js as well<\/a>.<\/p>\n\n\n<h1 class=\"wp-block-heading\">2011: A Glimmer in W3C Standard\u2019s Eye<\/h1>\n\n<p>With Angular.js continuing to grow within Google, it\u2019s no surprise that they continued researching in-JavaScript HTML bindings.<\/p>\n\n\n<p>On this topic, Alex Russel &#8211; then a Senior Staff Engineer at Google, working on the web platform team &#8211; <a href=\"https:\/\/fronteers.nl\/congres\/2011\/sessions\/web-components-and-model-driven-views-alex-russell\" target=\"_blank\" rel=\"noopener\">gave a talk at the Fronteers conference<\/a>.<\/p>\n\n\n<p>In this talk, he introduces a host of libraries that allow building custom elements with experimental new APIs.<\/p>\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">script<\/span>&gt;<\/span><span class=\"javascript\">\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Comment<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">HTMLElement<\/span> <\/span>{\n\n  <span class=\"hljs-keyword\">constructor<\/span>(attrs = {}) {\n    <span class=\"hljs-keyword\">super<\/span>(attrs);\n    <span class=\"hljs-keyword\">this<\/span>.textContent = attrs.text || lorem;\n    <span class=\"hljs-keyword\">this<\/span>.shadow = <span class=\"hljs-keyword\">new<\/span> ShadowRoot(<span class=\"hljs-keyword\">this<\/span>);\n    <span class=\"hljs-keyword\">this<\/span>.buildUI();\n  }\n\n  buildUI() { ... }\n}\n\nHTMLElement.register(<span class=\"hljs-string\">'x-comment'<\/span>, Comment);\n\n<span class=\"hljs-keyword\">var<\/span> c = <span class=\"hljs-keyword\">new<\/span> Comment(<span class=\"hljs-string\">\"Howdy, pardner!\"<\/span>);\n<span class=\"hljs-built_in\">document<\/span>.body.appendChild(c);\n<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">script<\/span>&gt;<\/span>\n\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">x-comment<\/span>&gt;<\/span>...<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">x-comment<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Here, he utilized the <a href=\"https:\/\/web.archive.org\/web\/20210311050620\/https:\/\/github.com\/google\/traceur-compiler\" target=\"_blank\" rel=\"noopener\">TraceUR compiler<\/a> (a precursor to Babel) to add classes (remember, <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Classes\" target=\"_blank\" rel=\"noopener\"><code>class<\/code> wouldn\u2019t land in JavaScript stable until ES6 in 2015<\/a>) to build a new \u201ccustom element\u201d.<\/p>\n\n\n\n<p>This combined with their <a href=\"https:\/\/web.archive.org\/web\/20110509081454\/http:\/\/code.google.com\/p\/mdv\" target=\"_blank\" rel=\"noopener\">new MDV library<\/a> in order to create a similar development environment to what we have in browser APIs today.&nbsp;<\/p>\n\n\n<p>It\u2019s important to note that at this stage, nothing was formalized inside of a specification &#8211; It was all experimental libraries acting as playgrounds for APIs.<br><br>That would change soon after.<\/p>\n\n<h1 class=\"wp-block-heading\">2013: Things Start Heating Up<\/h1>\n\n\n<p>In early 2013 the Google team created a <a href=\"https:\/\/web.archive.org\/web\/20130608123733\/http:\/\/www.w3.org\/TR\/custom-elements\/\" target=\"_blank\" rel=\"noopener\">Working Draft of a specification for Custom Elements<\/a>. Alongside similar working drafts for Shadow DOM APIs, they were colloquially called \u201c<a href=\"https:\/\/www.html5rocks.com\/en\/tutorials\/webcomponents\/customelements\/\" target=\"_blank\" rel=\"noopener\">Custom Elements v0<\/a>\u201d.<\/p>\n\n\n\n<p>With <a href=\"https:\/\/googleblog.blogspot.com\/2008\/09\/fresh-take-on-browser.html\" target=\"_blank\" rel=\"noopener\">Google Chrome\u2019s release in 2008<\/a>, 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.<\/p>\n\n\n\n<p><br>One such example of this was <a href=\"https:\/\/web.archive.org\/web\/20130515211406\/http:\/\/www.polymer-project.org\/\" target=\"_blank\" rel=\"noopener\">Polymer, which was a component library based on v0 APIs to provide two-way UI binding using MVC.<\/a> It\u2019s initial alpha release was announced in early 2013, alongside the specifications.<\/p>\n\n\n\n<p>At <a href=\"https:\/\/www.youtube.com\/watch?v=DH1vTVkqCDQ\" target=\"_blank\" rel=\"noopener\">Google Dev Summit 2013, they walked through its capabilities <\/a>and how it was able to run in other browsers by utilizing polyfills.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-css-opacity\"\/>\n\n\n\n<p>Facebook, not one to be outdone on the technical engineering front, <a href=\"https:\/\/www.youtube.com\/watch?v=GW0rj4sNH2w\" target=\"_blank\" rel=\"noopener\">introduced React into public in 2013<\/a><\/p>\n\n\n\n<p>While Polymer went deeper into the MVC route, <a href=\"https:\/\/coderpad.io\/blog\/development\/master-react-unidirectional-data-flow\/\">React relied more heavily on unidirectionality<\/a> in order to avoid state mutations.<\/p>\n\n\n<h1 class=\"wp-block-heading\">2016 &amp; 2017: Formative Years<\/h1>\n\n\n<p>While only the year prior, Polymer 1.0 was released with the usage of v0 custom element spec, <a href=\"https:\/\/web.archive.org\/web\/20161030051600\/http:\/\/w3c.github.io\/webcomponents\/spec\/custom\/\" target=\"_blank\" rel=\"noopener\">2016 saw the release of the custom element v1 specification<\/a>.<\/p>\n\n\n<p><br>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\u2019t have a v0 implementation.<\/p>\n\n\n<p>While <a href=\"https:\/\/web.archive.org\/web\/20161101052413\/http:\/\/caniuse.com\/#feat=custom-elementsv1\" target=\"_blank\" rel=\"noopener\">v1 was already implemented into Chrome in late 2016<\/a>, it wasn\u2019t until 2017 with the release of Polymer 2.0 that it would be adopted back into the library that helped draft the specification.<\/p>\n\n\n\n<p>Because of this, while <a href=\"https:\/\/blog.youtube\/news-and-events\/a-sneak-peek-at-youtubes-new-look-and\/\" target=\"_blank\" rel=\"noopener\">YouTube\u2019s new Polymer rewrite<\/a> theoretically was a huge step towards the usage of web components, it posed a problem. Browsers like <a href=\"https:\/\/web.archive.org\/web\/20180724154806\/https:\/\/twitter.com\/cpeterso\/status\/1021626510296285185\" target=\"_blank\" rel=\"noopener\">Firefox without a v0 implementation were forced to continue to use Polyfills<\/a>, which are slower than native implementations.<\/p>\n\n\n<h1 class=\"wp-block-heading\">2018 and Beyond: Maturity<\/h1>\n\n\n<p>2018 is where Web Components really found their foothold.<br><br>For a start, <a href=\"https:\/\/www.mozilla.org\/en-US\/firefox\/63.0\/releasenotes\/\" target=\"_blank\" rel=\"noopener\">Mozilla implemented the v1 specification APIs into their stable release of Firefox<\/a>, complete with dedicated devtools. Finally, developers could use all of the web components\u2019 APIs in their app, cross-browser, and without any concern for non-Chrome performance.<\/p>\n\n\n\n<p>On top of that, React\u2019s unidirectionality seemed to have won over the Polymer team. The Polymer team announced that it would <a href=\"https:\/\/www.polymer-project.org\/blog\/2018-05-02-roadmap-update#libraries\" target=\"_blank\" rel=\"noopener\">migrate away from bidirectional binding and towards a one-way bound <code>LitElement<\/code><\/a><\/p>\n\n\n\n<p>That <code>LitElement<\/code> would then turn into a dedicated framework called \u201c<a href=\"https:\/\/coderpad.io\/blog\/development\/web-components-101-lit-framework\/\">Lit<\/a>\u201d, developed to replace Polymer as its successor, that would hit <a href=\"https:\/\/github.com\/lit\/lit\/releases\/tag\/v1.0.0\" target=\"_blank\" rel=\"noopener\">v1 in 2019<\/a> and <a href=\"https:\/\/github.com\/lit\/lit\/releases\/tag\/lit%402.0.0\" target=\"_blank\" rel=\"noopener\">v2 in 2021<\/a>.<\/p>\n\n\n<h1 class=\"wp-block-heading\">Timeline<\/h1>\n\n<p>Whew! That\u2019s a lot to take in. Let\u2019s see it all from a thousand foot view:<\/p>\n\n<ul class=\"wp-block-list\"><li>2010:&nbsp;<ul><li><a href=\"https:\/\/github.com\/knockout\/knockout\/releases\/tag\/v1.0.0\" target=\"_blank\" rel=\"noopener\">Knockout.js released<\/a><\/li><li><a href=\"https:\/\/github.com\/jashkenas\/backbone\/releases\/tag\/0.1.0\" target=\"_blank\" rel=\"noopener\">Backbone.js alpha released<\/a><\/li><li><a href=\"https:\/\/web.archive.org\/web\/20100413141437\/http:\/\/getangular.com\/\" target=\"_blank\" rel=\"noopener\">Angular.js made open-source<\/a><\/li><\/ul><\/li><\/ul>\n\n<ul class=\"wp-block-list\"><li>2011:<ul><li><a href=\"https:\/\/fronteers.nl\/congres\/2011\/sessions\/web-components-and-model-driven-views-alex-russell\" target=\"_blank\" rel=\"noopener\">MDV (Polymer predecessor) introduced at a conference<\/a><\/li><\/ul><\/li><\/ul>\n\n<ul class=\"wp-block-list\"><li>2013:<ul><li><a href=\"https:\/\/web.archive.org\/web\/20130608123733\/http:\/\/www.w3.org\/TR\/custom-elements\/\" target=\"_blank\" rel=\"noopener\">Working draft spec for Web Components (v0) released<\/a><\/li><li><a href=\"https:\/\/www.youtube.com\/watch?v=DH1vTVkqCDQ\" target=\"_blank\" rel=\"noopener\">Polymer (Google\u2019s web component framework) announced<\/a><\/li><li><a href=\"https:\/\/www.youtube.com\/watch?v=GW0rj4sNH2w\" target=\"_blank\" rel=\"noopener\">React open-sourced<\/a><\/li><\/ul><\/li><\/ul>\n\n<ul class=\"wp-block-list\"><li>2015:<ul><li><a href=\"https:\/\/web.archive.org\/web\/20150814004009\/https:\/\/www.polymer-project.org\/1.0\/\" target=\"_blank\" rel=\"noopener\">Polymer 1.0 released<\/a><\/li><\/ul><\/li><\/ul>\n\n<ul class=\"wp-block-list\"><li>2016:<ul><li><a href=\"https:\/\/web.archive.org\/web\/20161030051600\/http:\/\/w3c.github.io\/webcomponents\/spec\/custom\/\" target=\"_blank\" rel=\"noopener\">Custom elements v1 spec released<\/a><\/li><li><a href=\"https:\/\/blog.youtube\/news-and-events\/a-sneak-peek-at-youtubes-new-look-and\/\" target=\"_blank\" rel=\"noopener\">YouTube rewritten in Polymer<\/a><\/li><\/ul><\/li><li>2017:<ul><li><a href=\"https:\/\/github.com\/Polymer\/polymer\/releases\/tag\/v2.0.0\" target=\"_blank\" rel=\"noopener\">Polymer 2.0 released<\/a><\/li><\/ul><\/li><\/ul>\n\n<ul class=\"wp-block-list\"><li>2018:<ul><li><a href=\"https:\/\/www.polymer-project.org\/blog\/2018-05-02-roadmap-update#libraries\" target=\"_blank\" rel=\"noopener\">Polymer announces start of migration to \u201cLitElement\u201d<\/a><\/li><li><a href=\"https:\/\/www.mozilla.org\/en-US\/firefox\/63.0\/releasenotes\/\" target=\"_blank\" rel=\"noopener\">Firefox enables web components (Polyfills no longer needed)<\/a><\/li><\/ul><\/li><\/ul>\n\n<ul class=\"wp-block-list\"><li>2019:<ul><li><a href=\"https:\/\/github.com\/lit\/lit\/releases\/tag\/v1.0.0\" target=\"_blank\" rel=\"noopener\">Lit framework 1.0 released<\/a><\/li><\/ul><\/li><\/ul>\n\n<ul class=\"wp-block-list\"><li>2021<ul><li><a href=\"https:\/\/github.com\/lit\/lit\/releases\/tag\/lit%402.0.0\" target=\"_blank\" rel=\"noopener\">Lit 2.0 released<\/a><\/li><\/ul><\/li><\/ul>\n\n<h1 class=\"wp-block-heading\">Conclusion<\/h1>\n\n<p>In the past 10 years we\u2019ve seen massive changes to the web development ecosystem. No more is this more apparent than the development and continued growth of web components.<\/p>\n\n\n<p>Hopefully this should put any future learnings about web components and <a href=\"https:\/\/coderpad.io\/blog\/development\/web-components-101-framework-comparison\/\">framework comparisons<\/a> into perspective.<\/p>\n\n\n<p>We\u2019ve waited a long time to see many of these ideas fully standardized into the web platform, and, now that they\u2019re here, they\u2019re helping accelerate growth of many platforms.<\/p>\n\n\n<p>Want to learn how to build them yourself?<br><br>We have articles about how to build web components <a href=\"https:\/\/coderpad.io\/blog\/development\/intro-to-web-components-vanilla-js\/\">without a framework<\/a> as well as using <a href=\"https:\/\/coderpad.io\/blog\/development\/web-components-101-lit-framework\/\">Google\u2019s Lit framework<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>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?<\/p>\n","protected":false},"author":1,"featured_media":3731,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[9],"tags":[],"persona":[29],"blog-programming-language":[62],"keyword-cluster":[],"class_list":["post-3730","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-development"],"acf":[],"_links":{"self":[{"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/posts\/3730","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/comments?post=3730"}],"version-history":[{"count":10,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/posts\/3730\/revisions"}],"predecessor-version":[{"id":8054,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/posts\/3730\/revisions\/8054"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/media\/3731"}],"wp:attachment":[{"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/media?parent=3730"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/categories?post=3730"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/tags?post=3730"},{"taxonomy":"persona","embeddable":true,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/persona?post=3730"},{"taxonomy":"blog-programming-language","embeddable":true,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/blog-programming-language?post=3730"},{"taxonomy":"keyword-cluster","embeddable":true,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/keyword-cluster?post=3730"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}