- Web components podem parecer a versão de navegador dos componentes do React, mas na prática se aproximam mais de um modelo que coloca o HTML existente no centro e adiciona funcionalidade por cima
- A diferença principal está na renderização antes da execução do JavaScript: em vez de passar dados para um elemento customizado vazio, o mais natural é envolver um HTML significativo com um elemento customizado
- Um HTML web component estende a marcação existente, enquanto um elemento vazio que delega totalmente conteúdo e funcionalidade ao JavaScript se aproxima mais de um JavaScript web component
- Se a componentização ao estilo React está acostumada com substituição, web components exigem uma lógica de augmentação: adicionar funcionalidade sem remover o conteúdo
- Na plataforma web, como aconteceu com HTML5,
fetch e os movimentos ligados ao TypeScript, boas ideias tendem a sobreviver por muito tempo quando reforçam a tecnologia existente em vez de substituí-la
Web components e componentes React têm naturezas diferentes
- O nome “Web components” pode soar como o equivalente, na plataforma web, aos componentes do React
- O JSX do React usa a forma
<MyComponent>, e web components podem usar a forma <my-component>
- Mas tentar criar web components como se fossem componentes React pode gerar frustração rapidamente
- As duas tecnologias diferem em quais capacidades e formas de uso são priorizadas no design
- Quando se tenta usar uma como se fosse a outra, isso entra em conflito com a direção natural de cada tecnologia
HTML web components combinam mais com augmentação do que com substituição
- Um componente React típico pode receber dados via propriedades em um componente vazio, e o JavaScript renderiza todo o conteúdo
<UserAvatar
src="https://example.com/path/to/img.jpg"
alt="..."
/>
- Um web component também pode ser escrito dessa forma, pelo menos na aparência
<user-avatar
src="https://example.com/path/to/img.jpg"
alt="..."
></user-avatar>
- Mas a força própria dos web components está no fato de possibilitarem renderização antes do JavaScript
- Componentes React não conseguem operar dessa forma
- Por isso, em vez de um “componente-casca” vazio, faz mais sentido montar o conteúdo principal em HTML e depois envolvê-lo com um elemento customizado para adicionar funcionalidade
<user-avatar>
<img src="https://example.com/path/to/img.jpg" alt="..." />
</user-avatar>
- A distinção feita por Jeremy em “HTML web components” foca em saber se o elemento customizado estende a marcação existente
- Se o elemento customizado estiver vazio, então não é um HTML web component
- Se ele envolve e estende a marcação existente, fica mais próximo de um HTML web component
- Um “JavaScript web component” é uma forma em que o conteúdo e a funcionalidade de um elemento vazio dependem totalmente do JavaScript
<user-avatar
src="https://example.com/path/to/img.jpg"
alt="..."
></user-avatar>
- Sem JavaScript, essa forma não tem significado para o usuário final
- Já um HTML web component mantém significado e conteúdo mesmo sem JavaScript, e com JavaScript ganha funcionalidade adicional por cima disso
<user-avatar>
<img src="https://example.com/path/to/img.jpg" alt="..." />
</user-avatar>
Na web, a abordagem de augmentação dura mais
- O motivo de uma abordagem augmentativa funcionar bem na web é que a natureza da web incentiva melhorias progressivas resilientes e se adapta bem a mudanças repetidas em algo tão grande quanto a própria web
- Mesmo quando boas ideias de frameworks e bibliotecas do ecossistema web são absorvidas pela plataforma, elas muitas vezes entram como reforço, e não como substituição completa da tecnologia existente
- XHTML tentou substituir o HTML4, mas o HTML5 tentou reforçar o HTML4 — e o HTML5 venceu
- Bibliotecas de rede tentaram substituir
XMLHttpRequest, e as boas ideias acabaram migrando para o padrão fetch
- Hoje,
fetch também existe em vários ambientes fora do navegador
- Boas ideias do Sass e do jQuery também migraram para o navegador
- Boas ideias do TypeScript também estão chegando ao navegador como reforço, não como substituição, da tecnologia existente
- Também dá para ver web components como parte do movimento de levar o modelo de componentes do React para dentro do navegador, mas eles se aproximam mais de reforçar a forma como a web já funciona do que de substituí-la
- Se a ideia é escolher uma abordagem técnica duradoura, optar por augmentação e aprimoramento faz mais sentido do que substituição dentro da direção da web
1 comentários
Comentários do Hacker News
Eu esperava que este texto explicasse o que
user-avatarrealmente faz ou oferece, mas isso nunca ficou claroSe ele só contém estilo, não entendo por que não usar simplesmente uma classe CSS, e parece muito mais natural que
user-avatarreceba um atributosrcem vez de exigir que se coloque uma tagimgdentro dele toda vezEm vez de tentarem “substituir” o HTML, Vue/React/Angular parecem mais estar sendo construídos por cima de HTML/CSS/JS, e se a ideia fosse renderizar tudo em canvas essa afirmação seria mais convincente
Fiquei empolgado com Web Components quando foram anunciados pela primeira vez, mas os recursos nativos são insuficientes demais, e passa pouco a sensação de que realmente ajudam a construir web apps como um framework ajuda
As alternativas aos grandes frameworks, especialmente coisas como htmlx, parecem jQuery com um pouco de açúcar sintático, então isso soa como um grande retrocesso para construir web apps
Se “web app” significa algo como Google Sheets, concordo, mas esse movimento anti-React parece mais criticar o hábito de instalar um framework por padrão e construir tudo assim desde o início do que mirar nesses casos
Na prática, há muitos sites em que tudo o que se precisa é “um pouco de interatividade por cima”
A principal vantagem é o aprimoramento progressivo: a tag
imgjá tem um comportamento padrão, então dá para se apoiar na renderização básica e “reforçar” só o que for necessário com web componentsO componente
details-utilsreforça o comportamento do componente HTML nativodetailMesmo que o JavaScript esteja desativado por algum motivo, o componente
detailcontinua funcionando como originalmente, e quando o JavaScript está ativado ou termina de ser baixado ele ganha comportamentos aprimorados, como fechar ao clicar foraO que é reutilizável nessa abordagem é justamente esse reforço de comportamento
Foi vendo esse web component do criador do 11ty que entendi o ponto do texto, e a parte que eu sentia quando vi Web Components pela primeira vez — “no fim das contas ainda precisa de JavaScript e sem ele não funciona” — aparece no mesmo ponto no texto do Rich Harris: https://dev.to/richharris/why-i-don-t-use-web-components-2ci...
O htmx basicamente evita escrever JavaScript e estende o paradigma de HTML renderizado no servidor para atualizações parciais da página, em vez de recarregar a página inteira
Se quiser ver mais da ideia de “HTML Web Components”, estes textos também valem a leitura
https://meyerweb.com/eric/thoughts/2023/11/01/blinded-by-the... - “So there you have it: a few thousand words on my journey through coming to understand and work with these fully-Light-DOM web components, otherwise known as custom elements. Now all they need is a catchy name, so we can draw more people to the Light Side of the Web.”
https://adactio.com/journal/20618 sugere um nome plausível
É trabalhoso de escrever, então no fim você acaba precisando de um framework leve em cima de um framework embutido como Lit, e o Lit é maior até que o Preact
Além disso, ele não resolve problemas reais como gerenciamento de estado e roteamento, então é bem provável que você tenha de puxar mais coisas
Talvez você ganhe componentes reutilizáveis, mas quando penso se alguém num projeto com React realmente vai importar um web component feito internamente com Vue, a ideia não parece fazer muito sentido
A beleza e a elegância da web vieram de sua estrutura declarativa, e isso tornou possível observá-la e modificá-la
Shadow DOM sempre pareceu um desejo corporativo de erguer uma barreira de encapsulamento mais alta e mais rígida, e pessoalmente esse nunca foi um objetivo que eu compartilhasse
Este texto mostra como trabalhar com Light DOM pode ser algo composicional
Sempre achei que web components ou custom elements deveriam poder modificar por conta própria o DOM interno, mover seus filhos e criar novo conteúdo
Por exemplo, a página ou o framework pode inserir ícones, e o elemento de avatar do usuário pode inserir o nome ou elementos decorativos
Dito isso, uma preocupação com Light DOM/HTML Web Components é que o Shadow DOM traz algumas vantagens de desempenho
Como desenvolvedor, faz sentido na minha cabeça que ele possa reduzir o número de elementos que os seletores CSS precisam percorrer, e seria bom poder aproveitar essa vantagem de algum jeito
É realmente bom ver uma abordagem mais leve para custom elements e Web Components, e obrigado pelos links
A afirmação de que “pode ser renderizado antes do JavaScript. Um componente React nunca pode fazer isso” é difícil de sustentar de forma categórica, e com renderização no lado do servidor ele pode ser renderizado antes do JavaScript no cliente
O exemplo parece simples demais para demonstrar a tese do autor
Um componente web que lide com mudanças de estado seria um alvo melhor para comparação, e o argumento também teria ficado melhor
Existem soluções de hydration, mas em geral são piores, têm trade-offs surpreendentes e muitas vezes prejudicam a composabilidade
Vendo apenas o exemplo que encapsula uma tag
img, não ficou claro qual seria a vantagem, e embora dê para agrupar elementos comuns e reutilizá-los, ainda é preciso JavaScript para haver interatividadeO texto alternativo da imagem no exemplo hoje em dia também costuma ser dinâmico por causa da localização, então sem JavaScript o conteúdo pode acabar faltando
Acho que finalmente entendi a proposta dos Web Components: https://github.com/kennyfrc/cami.js
“No Build Steps, No Client-Side Router, No JSX, No Shadow DOM. We want you to build an MPA, with mainly HTML/CSS, and return HTML responses instead of JSON. Then add interactivity as needed.”
“Declarative templates with lit-html. Supports event handling, attribute binding, composability, caching, and expressions.”
Pessoalmente, gosto de uma classe no estilo de componentes de classe do React com máquina de estados embutida, inspirada no XState
https://github.com/codewithkyle/supercomponent/blob/master/s...
A direção parece bem parecida, e talvez a comunidade do HTMX seja maior
Se já usou, queria saber o que sentiu falta
“web components” não são uma coisa só, e também não se “cria um web component”
“Web Components” é o nome da API Web Components, que agrupa três coisas
O que você realmente cria são elementos personalizados, e aí pode usar Shadow DOM neles ou templates HTML
Das três partes, a mais importante são os elementos personalizados
A ideia central é “criar mais elementos HTML”, então você mesmo define por completo quais atributos e qual API JavaScript eles vão suportar
A forma de colocá-los na página, interagir com eles e escutar eventos é exatamente igual à dos outros elementos HTML
Se você sabe escrever páginas web do “jeito antigo”, então já sabe usar elementos personalizados; só precisa aprender a declará-los
Recentemente comecei a experimentar Web Components sem ambiente de build
Sem npm, bun, webpack ou algo do tipo, sem dependências, e escrevendo em TypeScript
O IntelliJ faz a compilação automática para JavaScript, e a visualização no navegador injeta um pequeno handler de detecção de mudanças para atualização em tempo real durante o desenvolvimento
Até agora não tive problemas
O que parece atrapalhar os Web Components são os HTML Modules
Seria bom poder apontar para um arquivo
.html, e não para um.js, para importar um web component, mas por enquanto, para usar templates ou algo mais complexo, é preciso fazer uma injeção feia como.innerHtml = \...``Achei que isso seria um problema, mas a IDE até que faz um bom parse das template strings
E esse também não é o único motivo que impede os Web Components
Acho difícil concordar com a afirmação de que “React não é um aprimoramento, e sim uma substituição”
No fim das contas, React também renderiza elementos HTML e anexa manipuladores de evento em JavaScript
Envolver um
imgem um componente React não tira a funcionalidade doimg; adiciona algo por cima, ou seja, é um aprimoramentoO autor pode ter trabalhado em outras bases de código React, mas, pela minha experiência, nós usamos os recursos nativos do navegador como estão, a menos que haja um motivo para não fazer isso
Talvez eu só tenha dado sorte
O ponto é que a abordagem de “HTML Web Component”, ao contrário do React, não depende de JavaScript para começar a renderizar
No React, pensando na renderização do navegador, é “carregamento da página → carregamento do componente”, enquanto em Web Components é mais próximo de “carregamento da página → renderização básica → carregamento do componente”
Quem desativa JavaScript ainda consegue ver alguma coisa com web components, mas no React pode acabar não vendo nada; e, com JavaScript, pode-se evoluir para um estado de renderização mais avançado
Por exemplo, se você atribuir
onchangea um elemento, o React entrega algo mais próximo de um eventoinputdo que de um eventochangeNa prática, não é exatamente nenhum dos dois, e sim um evento sintético mais próximo de
inputdo que dechangeSe você realmente quiser
change, precisa usar uma referência ao elemento e anexar o manipulador manualmente dentro de um efeitoSe você estiver retornando HTML do servidor com React, então envolver um
imgem um componente React realmente é um aprimoramento do elemento existenteMas, se tudo estiver sendo renderizado no lado do cliente, esse
imgno fim não pode ser separado do componente ReactPela minha experiência, React é excelente quando você deixa toda a estrutura da página sob responsabilidade dele, de cima a baixo, mas pode ficar difícil quando tenta encaixá-lo em uma estrutura já existente enquanto também faz coisas como renderização no servidor
Se você estiver buscando uma abordagem duradoura, a conclusão de escolher aprimoramento e melhoria progressiva em vez de substituição também bate com a minha experiência
Graças a essa filosofia, meus projetos web duraram bastante tempo com manutenção e dependências no mínimo
Web components devem fazer uma coisa só, enquanto frameworks JavaScript são mais próximos de um ecossistema inteiro
Eu criei um web component de player de vídeo que podia receber várias entradas, e a mais complexa era um arquivo torrent
Também dava para portar para Vue/React com StencilJS [0], mas ele já era perfeitamente utilizável sem isso
Bastava inserir a tag correspondente junto com a classe exportada em
awesomePlayer.js, e você tinha um player de vídeo HTML5 de copiar e colar que reproduzia torrentsTambém recomendo fortemente imitar elementos HTML existentes sempre que possível
Por exemplo, usei
srcporque é assim quevideofunciona, e isso permite que quem usa interaja sem precisar vasculhar a documentação[0] https://stenciljs.com/
Acho difícil concordar que componentes de frameworks frontend sejam totalmente voltados à substituição e não componíveis
Na superfície pode parecer isso, mas nos meus componentes eu uso bastante slots, e a implementação é fácil e funciona de forma natural
Já Web Components costumam ser demonstrados inserindo uma quantidade enorme de código para construir algo como um editor
Usar slots em Web Components é doloroso: você precisa anexar muitos nós manualmente, lidar com templates como strings e, para fazer algo um pouco mais complexo, até ouvir o evento
slotchangeNo fundo, isso acaba sendo usar a API do DOM, e, se essa API não fosse tão horrível, provavelmente nem teríamos migrado para frameworks frontend como React
Também não concordo com a alegação lateral de que XHTML fracassou por não ter aprimorado HTML
Na minha opinião, ele fracassou porque a aplicação precisava ser totalmente válida e essa validação era deixada para o cliente/navegador
Se você usasse XHTML de verdade, um pequeno erro no markup quebraria a página; por isso todo mundo validava XHTML por questão de preparação para o futuro, mas nenhuma empresa aceitaria o risco de o negócio inteiro quebrar porque uma tag
pnão foi fechada corretamente