- À plataforma web ainda falta uma API de templates declarativa de que os desenvolvedores realmente precisam
- Na maioria dos frameworks web modernos, templating é uma tecnologia central, mas a API DOM padrão não oferece uma forma segura e eficiente de criar e atualizar templates
- Isso acaba gerando inconvenientes e perda de desempenho para usuários, desenvolvedores, frameworks e até para a própria plataforma
- Este é o momento certo para introduzir uma API de templates, já que a experiência recente dos frameworks e os recursos do JavaScript amadureceram o suficiente para tornar sua implementação e padronização mais práticas
- Ao reunir diferentes modelos, como identidade de template e reatividade baseada em sinais, o texto aponta uma direção para a próxima geração de APIs de templates
Resumo da proposta
- Este texto explica o contexto e a necessidade de adicionar uma API de templates declarativa à plataforma web
- A API DOM é poderosa, mas o DOM padrão não possui uma API de templates para criar e atualizar vários nós com segurança e eficiência com base em dados
- Frameworks importantes como React, Vue e Angular têm o templating declarativo como elemento central, oferecendo várias vantagens em produtividade, segurança, desempenho, análise estática e renderização no servidor
- A ausência de uma API de templates faz com que usuários, desenvolvedores, frameworks e a própria plataforma enfrentem complexidade desnecessária, riscos de segurança, perda de desempenho e barreiras de entrada
- O texto defende que agora é o momento ideal para introduzir essa API, aproveitando a experiência acumulada nos frameworks e os recursos modernos do JavaScript para propor uma padronização gradual
Necessidade de templates e problemas atuais
- A API DOM é a base que impulsiona os recursos dinâmicos da plataforma web
- Porém, o DOM padrão não oferece um modo declarativo de definir com segurança uma árvore DOM a partir de dados e atualizá-la com eficiência
- Frameworks web modernos (React, Vue, Angular, Svelte etc.) oferecem templating declarativo
- O motivo da popularidade do templating declarativo inclui:
- Melhor usabilidade e legibilidade em comparação com APIs imperativas
- Reforço da segurança contra XSS. Os dados dentro do template são escapados automaticamente
- Desempenho de renderização eficiente e rápido
- Aumento da produtividade com análise estática, checagem de tipos e IntelliSense
- Suporte a renderização no servidor
Problemas da situação atual
- Usuários: carregamento inicial mais lento devido ao download de bibliotecas e ao atraso na renderização. Aumento do tamanho do código no cliente piora a UX
- Desenvolvedores: precisam de bibliotecas separadas (npm, CDN etc.) para usar templates. Isso aumenta a barreira de entrada e leva a carregamento não padronizado
- Frameworks: precisam implementar seus próprios motores de template. Há trade-offs pesados entre desempenho, recursos e tamanho de código
- Plataforma: fica em desvantagem na competição com apps nativos. Flutter e SwiftUI, por exemplo, oferecem sistemas de templates embutidos
Por que agora é o momento certo
- Tentativas passadas relacionadas a templates (E4X, E4H, html template literal etc.) falharam, mas naquela época havia fraquezas na atualização do DOM
- Frameworks e a comunidade acumularam recentemente boas práticas de API de templates em volume suficiente
- Já é possível propor uma API baseada em JavaScript. No JS padrão atual, tagged template literals já existem
- Entre desenvolvedores de JavaScript vanilla e a comunidade de Web Components, a demanda por manipulação conveniente do DOM continua crescendo
- Propostas de primitivas de baixo nível, como DOM Parts, também avançam em paralelo, mas uma API declarativa de alto nível pode oferecer utilidade maior e indicar um caminho evolutivo mais claro
Análise de bons exemplos de sintaxe de templates
- Sistemas de templates dominantes (React-JSX, Vue, Svelte, Angular etc.) são, em essência, baseados em uma sintaxe muito semelhante de marcação + bindings
- No caso de templates baseados em API JS, é comum que a expressão de template retorne uma descrição do DOM, e uma função de renderização separada aplique isso ao DOM real
- Tentativas antigas como E4X retornavam o próprio DOM, o que resultava em um modelo de atualização inferior
Possibilidades de uma API de templates baseada em JavaScript
- Com tagged template literals, é possível projetar uma API de templates sem introduzir novos recursos na linguagem JavaScript
- Já existem vários casos práticos demonstrativos, como JSX-to-Lit
Discussão sobre integração com JSX
- A padronização de JSX exige definição semântica complexa e semântica de runtime. O JSX em si é apenas sintaxe
- Como o JSX não padronizado atual é uma transformação puramente sintática, se uma API de templates padrão for introduzida no futuro, será possível conectá-la a compiladores de transformação de JSX para template literals
- Se houver uma padronização real de JSX depois, será fácil migrar para uma estrutura de tipos de dados alinhada à API de templates
Relação com APIs de templates baseadas em HTML
- Muitos desenvolvedores e comunidades pedem um sistema de templates baseado em HTML
- Porém, um sistema baseado em HTML exige projetar novas sintaxes e expressões para bindings, linguagem de expressões, estruturas de controle etc., tornando-o um trabalho muito maior
- O mesmo motivo explica por que frameworks recentes, como Lit, migraram de templates HTML para APIs JS
- Por isso, é mais provável que uma API de templates baseada em JS seja introduzida primeiro, com possibilidade de expansão gradual para uma API HTML no futuro
Maturidade da experiência de implementação de reatividade
- Diferentes modelos de reatividade já foram validados, como VDOM diffing (React), identidade de template (Lit) e sinais (fine-grained signals, Solid/Svelte/Vue etc.)
- Abordagens baseadas em VDOM são mais lentas, enquanto a combinação de identidade de template com modelo de sinais é rápida, eficiente e mais fácil de explicar
- A abordagem baseada em sinais exige que todos os dados sejam encapsulados em sinais, mas também pode ser combinada com dados comuns
Caminho de evolução e efeitos esperados
- A API de templates JS declarativa proposta traz benefícios diretos para JavaScript vanilla, Web Components e novos frameworks
- Também pode ser aproveitada por frameworks existentes como alvo de compilação, backend de runtime ou API com suporte direto
- Dá suporte tanto ao modelo de rerenderização quanto à reatividade baseada em sinais
- Além disso, cria a base para expansões futuras, como templates declarativos baseados em HTML e custom elements declarativos
- O escopo da API é estreito e claro, e a integração com APIs existentes (por exemplo, DOM Parts) também é simples
- Ainda assim, embora a API e a sintaxe na superfície sejam simples, a área de implementação subjacente — como DOM Parts e schedulers — é ampla, e a padronização e os testes exigirão colaboração
Encerramento
- O autor está discutindo esta proposta na issue do GitHub e pede a participação da comunidade, incluindo engenheiros de plataforma
1 comentários
Comentários no Hacker News
Acho engraçada a frase “nós sabemos o que é uma boa sintaxe de template”, porque, na prática, nunca houve nem consenso real sobre esse critério. Na minha opinião, em templates, a experiência visual é mais importante do que a perspectiva simbólica. Foi por isso que ferramentas antigas como o Dreamweaver fizeram tanto sucesso. Muitos designers também começam a aprender por ferramentas como o Photoshop pelo mesmo motivo. É uma pena que essa tentativa pareça estar recriando o XSLT. O problema essencial de templating é combinar estruturas mal construídas em um resultado bem construído. Indo além, existe o problema de representar entidades conectadas, mas que não pertencem à mesma árvore, como
labelefor. Se eu pudesse fazer mágica, preferiria que não tentassem forçar tudo de maneira estranha a se encaixar no layout padrão de documentos. Dá para resolver muitos problemas de UI de forma eficiente usando bem posicionamento absoluto, então fico me perguntando por que insistem tanto em delegar repetidamente até operações matemáticas para a máquinaConcordo com a parte de que isso parece uma recriação do XSLT. Eu não gostava muito de XML em si, mas o XSLT era realmente algo poderoso. Ainda é um recurso amplamente suportado nos navegadores. XML mostrava bem seus defeitos em configuração e IPC, por exemplo, mas a combinação de uma excelente linguagem de marcação com o poder de transformação do XSLT acabou sendo pouco aproveitada. O XSLT não se popularizou porque era uma DSL genuinamente declarativa e funcional. Muita gente fala bem de DSL, mas na prática muitas vezes é só um invólucro fino sobre a semântica procedural de uma linguagem popular. Com uma DSL bem projetada dá para fazer coisas complexas de forma simples, e acho que falta disposição para estudar isso
Você diz que uma sintaxe de template adequada depende principalmente de visualidade, e eu queria entender como chegou a essa conclusão. Para mim, isso soa mais como uma reclamação sobre o próprio HTML+CSS, ou seja, sobre a forma de geração. Também fiquei curioso com a menção ao posicionamento absoluto. Ele certamente é útil onde faz sentido, mas, quando usado para o layout como um todo, acaba sendo mais difícil de manter e quebra facilmente dependendo do tamanho da tela ou da quantidade de conteúdo. Até layout de jornal, na prática, depende de muitos elementos sutis de texto e tipografia, então não dá para resolver tudo só com posicionamento absoluto. Quando trabalho mais a fundo com CSS, muitas vezes foi mais rápido e fácil resolver problemas reorganizando depois um layout que começou com posicionamento absoluto para
flexou fluxo normal. Dá para encontrar utilidade comcalc()e unidades de viewport, mas, na prática, se o conteúdo ou o viewport não forem totalmente fixos, posicionamento absoluto não é a ferramenta adequadaJá vi esse argumento de que as pessoas dão voltas desnecessárias para obter o mesmo efeito que seria fácil e rápido com posicionamento absoluto, mas na web existe a exigência de que um documento fique bom em dispositivos de todos os tamanhos, orientações e desempenhos. Aplicativos comuns, como apps de Windows, não têm essa preocupação, e apps mobile podem se limitar a tamanhos de tela padronizados. Só a web precisa lidar com tudo isso ao mesmo tempo
Reagir com sarcasmo à expressão “boa sintaxe de template” não me parece uma atitude muito respeitosa com quem está propondo progresso. E acho que hoje já existe sim uma boa sintaxe de template: JSX é o principal exemplo. Eu não sou fã de React, mas acho que o JSX revolucionou o desenvolvimento web, e que a maioria dos sistemas de template em JS convergiu quase toda para “template como expressão”, “composição por aninhamento” e controle de fluxo tratado em JavaScript
React e Svelte só se parecem na superfície; na prática, o modo como funcionam é bem diferente. O ponto central do React é que uma função JavaScript (quase) comum retorna marcação lazy em forma de JSX. Não existe uma sintaxe própria de template para loop ou renderização condicional; tudo isso é tratado em JavaScript normal, e essa é uma diferença importante
Vivo reaprendendo que API e ABI (interface binária de aplicação) nunca são realmente finais. As necessidades dos apps não são fixas; continuam mudando com o tempo, então não existe uma API perfeita que sirva para sempre. Esta proposta é um bom exemplo disso. Primeiro o problema é resolvido por bibliotecas em userland, como React, e depois chega o momento em que isso desce para o padrão. Polyfills seguem o mesmo padrão. Mesmo que uma proposta dessas tenha sucesso, ela também acaba envelhecendo, e as pessoas criam novos jeitos de contorná-la. DOM API, ECMA, navegadores antigos, tudo segue o mesmo destino. Isso me faz pensar se entropia técnica, extensibilidade e compatibilidade retroativa podem ser consideradas casos de uso normais da própria padronização
Adicionar novos recursos aos padrões web inevitavelmente cria uma carga enorme de código para manutenção, e os navegadores que seguem o padrão precisam implementar cada vez mais coisas. Projetos como o Servo ficam presos em uma situação em que só conseguem correr atrás da expansão contínua. Eu gostaria que a plataforma web tivesse todos os recursos do ambiente nativo, dentro das limitações de privacidade e sandbox. Também quero uma ótima experiência para desenvolvedores. Mas, para realizar esse sonho, é preciso considerar o custo do aumento de complexidade. Tenho dúvidas se esse templating nativo em discussão realmente vai melhorar de forma clara a experiência do desenvolvedor
Se a compatibilidade retroativa for mantida e a interface não mudar, então o versionamento não cumpriria justamente esse papel?
A afirmação é que, com o tempo, sempre acabamos contornando ou remendando as coisas, mas nesse processo também existe o efeito positivo de elevar o nível das funcionalidades de base. Atualizações incrementais continuam valendo muito a pena, mesmo quando as demandas dos usuários seguem revelando novas lacunas e casos de uso
Não concordo com a afirmação de que “API e ABI nunca são estáveis para sempre”. Por exemplo,
getElementByIdcontinua estável há mais de 25 anos. Dizer que APIs imutáveis são impossíveis me parece mais uma espécie de resignação pessoal, e há inúmeros contraexemplos no mundo real. A demanda é infinita; basta adicionar APIs novas. Não há necessidade de quebrar APIs que já funcionamNa web, uma vez que uma API é publicada, sempre haverá alguém que depende exatamente daquela forma pelo resto da vida. Por isso, às vezes ainda sentimos os efeitos de decisões tomadas há 20 anos. Isso pode ser visto em casos como “smooshgate”
Mencionando a onda da programação reativa, a ideia é que o userland já experimentou bastante nessa área e que agora seria possível criar um sistema realmente padrão reunindo apenas o melhor de várias abordagens. Mas em lugares como Ryan Carniato/Solid JS ainda continuam explorando novas possibilidades com signals, então não acho que essa exploração tenha acabado. Ainda há bastante espaço para evoluir
A web realmente precisa de templates nativos, reatividade e data binding. O desperdício de CPU e largura de banda no mundo inteiro, com bilhões de usuários baixando, fazendo parse e executando frameworks pesados como React, é quase inimaginável
Comparado ao desperdício gigantesco de recursos de LLMs e operações criptográficas, esse desperdício acaba parecendo pequeno
Há uma proposal sobre signals no TC39, e isso está ajudando a avançar mais um passo
Na prática, para desenvolvimento, o que basta é data binding bidirecional e algo como um clone de JSX
React não é um sistema de templates
Observando essa discussão sobre introduzir um sistema de templates de alto nível nos padrões web, acho que o que deveria vir primeiro são APIs de baixo nível embutidas no navegador. É quase impossível fazer todo mundo concordar com um sistema de templates padrão. Em vez disso, bastaria o navegador fornecer uma API de baixo nível para aplicar diff ao DOM. Por exemplo, seria ótimo ter nativamente um método como:
element.applyDiff(DocumentFragment | string, { method: 'innerHTML' | 'outerHTML' }). Ao aplicar o diff dessa forma, seria possível atualizar de modo não destrutivo preservando foco atual do elemento, valor de inputs, estado de áudio/vídeo etc. Existem bibliotecas JS como Idiomorph, mas uma solução nativa provavelmente seria muito mais rápidaO autor deste texto é apresentado como alguém com experiência de altíssimo nível nessa área. Ele contribuiu fortemente para Lit, Polymer, web components do Google e várias especificações centrais do DOM
Em vez da abordagem com JSX, eu gostaria de uma abordagem sintática parecida com a generalização que Kotlin faz de DSL usando receiver e builder. Esse tipo de abordagem poderia ser extremamente útil não só para templates HTML simples, mas também para várias hierarquias de componentes, configuração e diferentes contextos. O significado real de templating e data binding, no fim, não passa de um conjunto padrão de funções que usa esse tipo de recurso sintático, algo semelhante ao Jetpack Compose
Nem sempre consigo me convencer de que templating declarativo é melhor do que jQuery. Uso React há quase 10 anos, mas, quanto mais complexa minha SPA fica, mais sinto falta do controle imperativo do DOM. A abstração do DOM vaza, e, no fim, padrões simples como “last-write-wins” às vezes ficam até mais claros. Dizem que templates declarativos resolvem isso, mas, quando você começa a compartilhar estado mutável entre componentes, os limites aparecem rápido demais
Parte dessa sensação também vem de desenvolvedores de React tratarem chamadas diretas à DOM API como se fossem pecado. Usar
refativamente ou encontrar e manipular componentes diretamente poridtambém é perfeitamente válido. Na prática, bibliotecas de formulários rápidas e com poucos rerenders funcionam justamente assimEu não gosto muito de React, mas também não acho que exista barreira real para sair do DOM declarativo e usar
innerHTML,refetc. O controle imperativo é possível, mas, em termos práticos, há pouca coisa que não possa ser feita de forma declarativa.attachShadow()eshowModal(), por exemplo, também podem ser facilmente encapsulados de forma declarativa com umas 10 linhas a maisSe a proposal de Records e Tuples tivesse avançado, o JSX poderia ter usado essas estruturas para ganhar uma nova semântica, mas, na prática, essa proposal não apenas parou como foi totalmente retirada (veja a issue). No lugar dela, entrou a proposal de composites
Acho que esse tipo de discussão sobre padronizar recursos de alto nível deveria parar. Em vez disso, seria melhor expandir as características de baixo nível e focar em direções que tragam mais valor para a implementação de bibliotecas de nível superior. Se uma proposal de padrão não tiver vantagens claras sobre uma biblioteca, então ela não faz sentido. Na minha opinião, só deveríamos começar a discutir padronização depois de algo ter sido amplamente validado em bibliotecas por pelo menos 5 a 10 anos