2 pontos por GN⁺ 2023-11-14 | 1 comentários | Compartilhar no WhatsApp
  • 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

 
GN⁺ 2023-11-14
Comentários do Hacker News
  • Eu esperava que este texto explicasse o que user-avatar realmente faz ou oferece, mas isso nunca ficou claro
    Se ele só contém estilo, não entendo por que não usar simplesmente uma classe CSS, e parece muito mais natural que user-avatar receba um atributo src em vez de exigir que se coloque uma tag img dentro dele toda vez
    Em 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

    • Concordo com a parte de que “as alternativas aos grandes frameworks parecem açúcar sintático em cima de jQuery”, mas não está claro por que isso seria uma escolha totalmente errada 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”
    • Acho que o texto do Eric Meyer mostra muito melhor a intenção: https://meyerweb.com/eric/thoughts/2023/11/01/blinded-by-the...
      A principal vantagem é o aprimoramento progressivo: a tag img já 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 components
    • Como faltam exemplos concretos, este texto parece um pouco uma ideia que surgiu no banho
    • Um exemplo melhor, que mostra de forma mais concreta o argumento do texto, é este aqui: https://www.zachleat.com/web/details-utils
      O componente details-utils reforça o comportamento do componente HTML nativo detail
      Mesmo que o JavaScript esteja desativado por algum motivo, o componente detail continua funcionando como originalmente, e quando o JavaScript está ativado ou termina de ser baixado ele ganha comportamentos aprimorados, como fechar ao clicar fora
      O 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...
    • Não sei se você já usou htmx, mas essa crítica parece fora do alvo, porque ele trata de um problema diferente daquele que o jQuery resolvia, de experiência do usuário com JavaScript no cliente
      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

    • Não entendi muito bem o ponto
      É 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
    • Fico realmente feliz de ver um movimento defendendo web components sem Shadow DOM
      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
    • Talvez dê para encurtar esse nome plausível ainda mais e chamar de HTML components
  • 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

    • É uma boa observação, e, por outro lado, também se pode dizer que os web components não conseguem fazer isso, já que precisam ser registrados via JavaScript antes de a página carregar
      Existem soluções de hydration, mas em geral são piores, têm trade-offs surpreendentes e muitas vezes prejudicam a composabilidade
    • O maior problema dos Web Components é que não são amigáveis à renderização no lado do servidor
    • Não sei como um “HTML Web Component” lidaria com mudanças de estado
      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 interatividade
      O 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.”

    • A beleza dos Web Components está em poder encontrar ou criar uma classe base que funcione do jeito que você precisa
      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...
    • Fico curioso se você já usou HTMX
      A direção parece bem parecida, e talvez a comunidade do HTMX seja maior
      Se já usou, queria saber o que sentiu falta
    • É como trocar JSX por uma DSL personalizada não padronizada e chamar isso de vitória
  • “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

    • HTML Modules foram abandonados e removidos, sendo substituídos por imports exclusivos de JavaScript
      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 img em um componente React não tira a funcionalidade do img; adiciona algo por cima, ou seja, é um aprimoramento
    O 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

    • Que qualquer arquitetura web acabe renderizando elementos HTML é óbvio, e esse não era o ponto
      O ponto é que a abordagem de “HTML Web Component”, ao contrário do React, não depende de JavaScript para começar a renderizar
    • Acho que a principal diferença que o texto quer apontar é mais ou menos esta
      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
    • Em alguns casos, React também dificulta o acesso aos recursos nativos
      Por exemplo, se você atribuir onchange a um elemento, o React entrega algo mais próximo de um evento input do que de um evento change
      Na prática, não é exatamente nenhum dos dois, e sim um evento sintético mais próximo de input do que de change
      Se você realmente quiser change, precisa usar uma referência ao elemento e anexar o manipulador manualmente dentro de um efeito
    • Depende da arquitetura da aplicação
      Se você estiver retornando HTML do servidor com React, então envolver um img em um componente React realmente é um aprimoramento do elemento existente
      Mas, se tudo estiver sendo renderizado no lado do cliente, esse img no fim não pode ser separado do componente React
    • Ao ler essa parte, pensei no caminho inverso, ou seja, colocar React dentro de outro HTML
      Pela 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 torrents
    Também recomendo fortemente imitar elementos HTML existentes sempre que possível
    Por exemplo, usei src porque é assim que video funciona, 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 slotchange
    No 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 p não foi fechada corretamente