TL;DR
Web Components hoje são parte fundamental da plataforma web — um padrão consolidado, suportado nativamente por todos os navegadores modernos. Neste drop vou cobrir os pilares que sustentam esse padrão e deixar claro como ele se encaixa no desenvolvimento web atual.
Tentarei ser bastante sucinto com relação a conceitos técnicos, pois pretendo salientar os tópicos de forma mais pessoal, até porque existem inúmeros drops conceituais do assunto na web e também porque futuramente vou fazer drops mais aprofundados sobre alguns tópicos a seguir (e.g. No fim do drop deixarei alguns links).
Mas vamos lá…
Web components, um padrão criado por padrões

Falar de Web Components, é o mesmo que falar de vários assuntos ao mesmo tempo, sem dúvidas nem nesse drop e provavelmente em nenhum drop relacionado você encontrará tudo sobre o assunto, aliás, o que geralmente é encontrado são referências replicadas, poucos são os artigos diferenciados ou que abordam assuntos mais técnicos e aprofundados sobre o tema.
Os pilares do padrão Web Components são: Custom Elements, HTML Templates, Shadow DOM e ES Modules.
Irei abordar cada um destes tópicos a seguir (e um pouquito mais…)
Custom Elements
Custom Elements talvez seja o padrão que cria mais assimilação para a maioria com relação aos padrões dentro de Web Components.
E isso é muito natural, pois Custom Elements possibilita de forma bem explícita a criação de elementos diferenciados, transformando o desenvolvedor num “web maker”, ou seja, o desenvolvedor deixa de ficar limitado a apenas <button>, <div>, etc. Podendo criar seus próprios elementos HTML com estrutura, comportamento e estilo único.
Já pensou em criar, enfim, um elemento <tab> ou <pagination>? Deixaria bem mais semântico seu código, né?
Por exemplo, dê uma olhada na estrutura do Carousel do Twitter Bootstrap:
<div id="carousel" class="carousel slide" data-ride="carousel">
<ol class="carousel-indicators">
<li data-target="#carousel" data-slide-to="0" class="active"></li>
<li data-target="#carousel" data-slide-to="1"></li>
<li data-target="#carousel" data-slide-to="2"></li>
</ol>
<div class="carousel-inner">
<div class="item active">
<img src="..." alt="..." />
</div>
<div class="item">
<img src="..." alt="..." />
</div>
...
</div>
<a
class="left carousel-control"
href="#carousel"
role="button"
data-slide="prev"
>
<span class="glyphicon glyphicon-chevron-left"></span>
</a>
<a
class="right carousel-control"
href="#carousel"
role="button"
data-slide="next"
>
<span class="glyphicon glyphicon-chevron-right"></span>
</a>
</div>
Imagine poder encapsular todo esse “divnation” ou “listnation” junto com logica e estilo do Carousel e exibir apenas isso publicamente:
<my-carousel>
<img src="images/x.jpg" alt="imagem X" />
<img src="images/y.jpg" alt="imagem Y" />
<img src="images/z.jpg" alt="imagem Z" />
...
</my-carousel>
Bem melhor, concorda? E repare principalmente que agora temos um elemento customizado chamado: <my-carousel>. Mas explicar isso fica a cargo dos próximos tópicos. :)
Templates
Antes de falar sobre o novo padrão para Templates, é importante também mostrar como atualmente nós fazemos o controle de templates. E para isso, observe o seguinte exemplo:
<script id="entry-template" type="text/x-handlebars-template">
template content
</script>
E este outro:
<div hidden>template content</div>
Talvez em primeiro momento pra você estas sejam formas “elegantes” de se trabalhar com um pequeno pedaço de código e obter controle do mesmo, além de também poder reutilizá-lo (afinal, é um template), mas na verdade, tais aplicações são “gambiarras bonitinhas”, que como o Flash um dia representou a única opção para implementar vídeos, mas que hoje não é extremamente necessário, pois possuímos a tag <video>, a especificação de Web Components trás consigo uma nova forma de definir pequenos pedaços de códigos reutilizáveis, e para isso, basta utilizarmos a nova tag <template>. E digo mais, o principal plus de se utilizar esta feature, é que ela deixa seu conteúdo inerte, ou seja, se você possui uma tag <img src="imagem.jpg"> dentro da tag <template> que tecnicamente faria a requisição de seu source, não precisará fazer “magias” para controlar essa requisição, pois o browser, irá fazer isso pra você e liberar o request apenas quando você quiser.
Veja um exemplo de aplicação:
<template id="mycard">
<img src="images/me.jpg" />
<div class="name">Beto Muniz</div>
</template>
Muito simples não é? Não sei você, mas eu acho muito f*******a!!! E ainda não terminamos…Continue lendo, pois o proximo tópico é sensacional.
Shadow DOM
Bom, depois de um breve momento de frenesi, duas dúvidas surgem: Tenho um elemento customizado e com um template, posso usar ele em qualquer lugar agora? Possuo agora, um Web Component?
A resposta é: Ainda não. oO
Infelizmente, você ainda não pode pegar este elemento e sair aplicando em todos os projetos que você possui, pois de certa forma o escopo dele está “público”, ou seja, uma regra CSS ou uma manipulação Javascript no DOM feita dentro do escopo de sua aplicação, pode influenciar e causar um comportamento indesejado do seu elemento, mas não desanime, pois é possível delimitar um escopo do seu próprio elemento e para isso foi criada uma solução chamada de Shadow DOM.

Basicamente, o padrão Shadow DOM foi pensado para permitir certa independência e isolamento do componente, para que o mesmo seja assegurado de que nada externamente e fora dos planos do que foi pensado para o elemento seja modificado.
Vejamos o exemplo da tag <video>: (sim, a tag <video>__, como outras, foram feitas utilizando-se dos conceitos de Web Components):

Verifique que ela possui uma declaração #shadow-root, e é a partir desta declaração que o “confinamento” do comportamento do seu elemento é respeitada pelo browser e por sua aplicação, sem contar também que a partir desta declaração uma subárvore de DOM é criada, o que também evita assimilar este padrão ao uso de <iframe>.
Mas já pensou se no nosso caso, não fosse possível criar este isolamento? Todos os controles por exemplo da tag <video> seriam afetados caso você criasse uma regra CSS ou manipulação global via Javascript para o elemento div, e é por isso, que para mim, este padrão é o que mais representa que acabamos de criar um componente totalmente independente e pronto para ser usado em qualquer projeto.
E para fins didáticos, a saída do exemplo anterior seria a seguinte:

ES Modules
Bacana, agora que temos um DOM (kkk) e um pequeno “mundo” sobre nosso controle, falta ainda ter a possibilidade de empacotar, distribuir, compartilhar e reutilizar de forma simples.
E para isso, usamos ES Modules, o padrão oficial do JavaScript para distribuir e reutilizar código — incluindo Web Components.
A definição do componente fica em um arquivo .js:
class MyCarousel extends HTMLElement {
constructor() {
super();
const shadow = this.attachShadow({ mode: "open" });
shadow.innerHTML = `<style>/* estilos */</style><slot></slot>`;
}
}
customElements.define("my-carousel", MyCarousel);
E o consumo é via <script type="module">:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Document</title>
<script type="module" src="customelements/my-carousel.js"></script>
</head>
<body>
<my-carousel>
<img src="images/x.jpg" alt="imagem X" />
<img src="images/y.jpg" alt="imagem Y" />
</my-carousel>
<my-carousel>
<img src="images/a.jpg" alt="imagem A" />
<img src="images/b.jpg" alt="imagem B" />
</my-carousel>
</body>
</html>
NOTA: Cada declaração tem seu próprio escopo (graças ao Shadow DOM), e o módulo é executado apenas uma vez mesmo que importado em vários lugares.
E espera, ainda não acabou!
Antes de concluir o drop, quero lembrar que os tópicos que abordei são oficialmente considerados como base do padrão Web Components, mas outros também são importantes para criar um ecossistema rico para componentes. Alguns que vale conhecer:
- Pointer Events, Web Animations API e MutationObserver — todos estáveis e bem suportados.
- Constructable Stylesheets e
adoptedStyleSheets— para compartilhar estilos entre componentes sem duplicação. - Form-Associated Custom Elements (
ElementInternals) — para integrar Custom Elements com<form>nativos. - Declarative Shadow DOM — para SSR de Web Components sem JavaScript.
Proxy— para observar e interceptar mudanças em objetos JavaScript usados como estado dos seus componentes.
Mas a moral da historia é…

A moral deste drop é que Web Components são parte fundamental da plataforma web — suportados nativamente por Chrome, Edge, Firefox e Safari — e usados em projetos como YouTube, GitHub, Salesforce Lightning, e por design systems inteiros como Adobe Spectrum, IBM Carbon, Lit, FAST, Stencil entre outros. Investir tempo aprendendo o padrão dá retorno em qualquer stack que você esteja usando.
E é isso, falei muito, mas falei tudo que eu queria e como eu queria, espero que tenham gostado. Qualquer dúvida ou caso queria agregar mais para o drop, é só comentar.
Referências:
- WebComponents.org
- CustomElements.io
- github.com/webcomponents
- A Guide to Web Components
- Web Components: Introdução
- A future called Web Components
- Web Components é uma Revolução?
▲