Os frameworks têm o seu lugar quando o tamanho do produto o justifica, mas existe um enorme espaço onde JavaScript vanilla bem organizado traz clareza às dependências e mantém os custos de entrada baixos tanto para desenvolvedores como para operações.
O erro comum é usar “vanilla” como sinónimo de um único ficheiro gigante. A solução é aplicar uma mentalidade de componente sem forçar um runtime específico.
O que Quero Dizer com Componente Neste Contexto
Um componente não é necessariamente JSX: é um pedaço autocontido com comportamento conhecido do lado do cliente, marcação acessível e estilos com um âmbito definido. Pode expor métodos públicos claros como mount, destroy, ou callbacks registados através de eventos DOM padrão.
A chave é que ninguém acede aos internos DOM de outro componente. Se precisar de comunicação, use Eventos Personalizados ou um pequeno canal de mensagens em memória onde os módulos se inscrevem por nome de tópico, não por referências imperativas entre si.
Estrutura de Pastas que Escala Suavemente
Um padrão que funciona muito bem para sites ricos em conteúdo ou dashboards de tamanho médio:
components/com uma pasta por bloco (hero/,filter-bar/, …) contendoComponent.ts,styles.css, e quando necessário,template.htmlou helpers.lib/para utilitários partilhados não ligados à UI.pages/apenas como composições que importam e montam componentes.
As folhas de estilo podem ser importadas do mesmo módulo ou concatenadas no tempo de construção se usar Astro, Vite, ou similar — o importante é a co-localização.
Desempenho Percebido e Bundle
Vantagem direta: carrega apenas o JS para o componente onde o HTML o marca. Comparado a uma árvore React que inicializa até mesmo vistas não visíveis, uma implementação bem feita de vanilla permite-lhe hidratar com um custo proporcional.
Isso ajuda quando a sua equipa prioriza o Lighthouse ou em mercados onde a velocidade influencia fortemente a conversão — um tópico intimamente relacionado a outras auditorias que publico sobre Core Web Vitals.
Migração à Medida que o Projeto Cresce
O caminho habitual é começar com uma marcação estática bem estruturada e semântica e adicionar camadas incrementais:
- Estado local em cada componente antes de expor estado global partilhado.
- Uma camada de “router” mínima que apenas mostra/esconde secções ou delega URLs.
- Opcionalmente mais tarde: adotar ferramentas que compilen para o mesmo modelo de Web Components se quiser reutilização em múltiplos projetos.
Critérios de Priorização para Projetos Reais
Para arquitetura de componentes vanilla, a questão útil é que decisão a equipa pode tomar de forma mais segura após ler o artigo. Traduza a ideia para um primeiro fluxo de trabalho, proprietário, requisito de evidência e plano de medição antes de se comprometer com a implementação.
Um Contrato de Componente Prático
Um componente vanilla deve ter um contrato que seja suficientemente aborrecido para ser mantido. No mínimo, defina o seletor que o ativa, os atributos de dados que lê, os eventos que emite e os métodos de ciclo de vida que expõe. Esse contrato permite que outro desenvolvedor use o componente sem abrir a sua estrutura interna DOM.
export function mountPricingToggle(root: HTMLElement) {
const buttons = [...root.querySelectorAll<HTMLButtonElement>('[data-plan]')];
function onClick(event: Event) {
const target = event.currentTarget as HTMLButtonElement;
root.dispatchEvent(new CustomEvent('pricing:changed', {
bubbles: true,
detail: { plan: target.dataset.plan }
}));
}
buttons.forEach((button) => button.addEventListener('click', onClick));
return {
destroy() {
buttons.forEach((button) => button.removeEventListener('click', onClick));
}
};
}
Este padrão proporciona-lhe uma desmontagem previsível, comportamento testável e uma carga útil de evento clara. Também evita um padrão anti-comum: um componente a aceder ao HTML de outro componente e a alterar detalhes de implementação privados.
Quando a Vanilla é Suficiente e Quando Não É
A arquitetura vanilla funciona especialmente bem para sites de marketing, sites de documentação, produtos renderizados no servidor, dashboards com widgets isolados, e projetos Astro onde a maioria das páginas são focadas em conteúdo. Torna-se frágil quando o produto tem estado do lado do cliente profundamente partilhado, UI otimista, roteamento complexo, edição colaborativa, ou muitas telas cujo comportamento depende do mesmo modelo de dados ao vivo.
| Situação | Abordagem de componente vanilla | Framework provavelmente justificado |
|---|---|---|
| Filtros, alternadores, calculadoras isolados | Adequação forte | Geralmente desnecessário |
| Site rico em conteúdo com algumas ilhas interativas | Adequação forte | Opcional |
| Grande estado partilhado em toda a aplicação | Possível mas arriscado | Adequação mais forte |
| Sistema de design reutilizável em muitos produtos | Web Components ou framework | Frequentemente justificado |
| Experimentação frequente de UI por múltiplas equipas | Funciona com disciplina | O framework pode reduzir a deriva |
A decisão deve ser baseada na forma do produto, não na popularidade de uma stack. Se o HTML é maioritariamente renderizado no servidor e a interação é local, um contrato de componente mais Eventos Personalizados é frequentemente mais simples do que enviar um runtime completo a cada visitante.
Testes e Verificações de Manutenibilidade
A barra mínima de qualidade é: os componentes podem ser montados mais de uma vez, destruídos sem vazamentos de listeners, operados com entrada de teclado, e testados com fixtures DOM realistas. Para acessibilidade, o componente não deve remover semântica nativa a menos que a substitua por comportamento ARIA correto e suporte a teclado.
Quando um componente começa a importar demasiados helpers não relacionados, a ler estado global, ou a exigir uma ordem específica de página, já não está isolado. Esse é o momento de dividir o componente ou introduzir uma pequena camada de aplicação intencionalmente em vez de deixar o acoplamento crescer por acidente.
Leitura Relacionada
- O Impacto Real do Desempenho na Conversão
- Sinais de que o Seu Sistema Web Precisa de uma Refatoração Urgente
- Agentes de IA para WordPress: Captura e Qualificação de Leads a partir da Web
Recomendação Final
A arquitetura baseada em componentes não requer sintaxe JSX ou um DOM virtual. O que requer são contratos claros, limites e disciplina — assim como qualquer equipa frontend madura — com o benefício adicional de carregar menos abstração quando o seu projeto ainda pode suportá-lo.
Perguntas frequentes
- Quando faz sentido a arquitetura de componentes em vanilla JavaScript?
- Faz sentido quando a camada de interação é limitada, a equipa quer baixo overhead, e os componentes podem ser expressos com contratos claros, estado local e melhoria progressiva.
- Quando deve uma equipa passar de componentes vanilla para um framework?
- Deve-se mudar quando o estado partilhado, roteamento, composição, testes e fluxo de trabalho da equipa se tornarem mais difíceis de manter do que o custo do framework. A decisão deve ser baseada na complexidade, não na preferência.
- O que deve incluir um componente vanilla manutenível?
- Deve definir o seu limite DOM, entradas, eventos, ciclo de vida, contrato de estilo, regras de acessibilidade e comportamento de limpeza.