Pacote de script sob medida: só o que a tela usa, e um comando para gerar de novo
Troque o arquivo combinado com "tudo marcado" por um pacote por tela, gerado a partir das importações, medido e reproduzível por um comando no repositório.
A tela de pedidos mostra um grid com 20 linhas e, antes de desenhar a primeira célula, baixa um kit-completo.min.js de 2,1 MB. Ninguém escolheu esse tamanho: alguém abriu o gerador de pacote do kit de componentes, marcou tudo "para não faltar nada" e subiu o resultado. A resposta curta: o pacote deve nascer das importações da página, não de uma lista de caixinhas, e precisa ser regenerado por um comando que está no repositório. Se você não consegue dizer o que tem dentro do arquivo combinado, também não consegue atualizá-lo com segurança.
O caso que atravessa este guia é a loja fictícia Casa Pinho. A área administrativa tem três telas (pedidos, clientes e relatório) e usa um kit comercial de componentes de interface. Vamos sair de um arquivo único marcado "tudo" para um pacote por tela, medido e reproduzível.
Por que marcar tudo deixa a página pesada e frágil
Um combinador online junta os arquivos que você escolhe num formulário. Ele não sabe o que a sua página chama. Marcando tudo, você recebe o grid, o calendário, o editor de texto rico, os gráficos e as dependências de cada um. O navegador baixa, descompacta e analisa todo esse JavaScript antes de executar, e isso custa CPU, principalmente no celular barato do cliente que abre o painel na rua.
O peso é o problema visível. O invisível é a fragilidade. O arquivo gerado vira um artefato órfão: ninguém lembra a versão do kit nem quais módulos foram marcados. Quando sai uma correção, alguém gera outro pacote marcando "tudo" de novo e agora vem um componente com API diferente. Ou alguém acrescenta a cópia do CDN ao lado da combinada, e as duas disputam o mesmo objeto global. Esse sintoma, com a biblioteca aparecendo como undefined, é o tema do guia sobre grid que carregou fora de ordem.
Descubra o que a tela usa de verdade
Antes de mexer no build, meça. No Chrome, abra o DevTools, chame o menu de comandos com Ctrl+Shift+P e procure por Coverage. Comece a gravação e recarregue a tela de pedidos. O painel mostra, por arquivo, quantos bytes foram executados e quantos ficaram parados. Na Casa Pinho, mais de 80% do arquivo combinado não rodou naquela tela.
A cobertura é pista, não lista final. Parte do código só roda quando a pessoa clica em ordenar ou exportar. Confirme olhando o seu próprio código: quais componentes você instancia, quais recursos liga (paginação, ordenação, filtro) e quais idiomas carrega. Escreva essa lista. Ela vira o arquivo de entrada do próximo passo.
Como gerar um pacote por tela com importação explícita
- Instale o kit pelo npm, com a versão travada no
package-lock.json. Muitos kits atuais publicam um pacote por componente justamente para permitir isso. - Crie um arquivo de entrada por tela, importando só o que ela usa.
- Gere o pacote com um empacotador (esbuild, Rollup, Vite ou webpack). O exemplo usa esbuild porque cabe numa linha.
- Coloque o comando no
package.json, para que qualquer pessoa da equipe gere o mesmo resultado. - Meça o tamanho comprimido e faça o build falhar se passar do limite combinado.
O arquivo de entrada da tela de pedidos
A tela usa só o grid, com paginação e ordenação. A importação diz exatamente isso, e quem ler o arquivo daqui a um ano entende o que está no pacote.
// src/telas/pedidos.js
import { Grid, Page, Sort } from '@syncfusion/ej2-grids';
Grid.Inject(Page, Sort);
async function montarGridDePedidos(seletor) {
const resposta = await fetch('/api/pedidos?limite=200', {
headers: { Accept: 'application/json' }
});
if (!resposta.ok) {
throw new Error('Falha ao carregar pedidos: HTTP ' + resposta.status);
}
const pedidos = await resposta.json();
const grid = new Grid({
dataSource: pedidos,
allowPaging: true,
allowSorting: true,
pageSettings: { pageSize: 20 },
columns: [
{ field: 'numero', headerText: 'Pedido', width: 110 },
{ field: 'cliente', headerText: 'Cliente', width: 200 },
{ field: 'total', headerText: 'Total', format: 'C2', textAlign: 'Right', width: 120 }
]
});
grid.appendTo(seletor);
}
montarGridDePedidos('#grid-pedidos').catch((erro) => {
console.error(erro);
document.querySelector('#grid-pedidos').textContent =
'Não foi possível carregar os pedidos. Recarregue a página.';
});
Repare no tratamento de erro. Se a API falhar, a pessoa lê uma frase, e não um quadrado vazio. O pacote menor não adianta nada se a tela continuar muda quando algo dá errado.
O comando de build no repositório
{
"scripts": {
"build:js": "esbuild src/telas/pedidos.js src/telas/clientes.js src/telas/relatorio.js --bundle --minify --format=esm --outdir=public/js --metafile=meta.json",
"size": "node scripts/tamanho.js"
}
}
Cada tela ganha o seu arquivo em public/js, e a página carrega só o dela com <script type="module" src="/js/pedidos.js"></script>. Se quiser ver quais módulos ocupam mais espaço, rode o mesmo comando com --analyze uma vez. A folha de estilo do kit segue a mesma lógica: a maioria dos kits separa o CSS por componente, e a tela de pedidos não precisa do estilo do editor de texto.
Medir e travar o tamanho
O arquivo meta.json que o esbuild gera lista cada saída com o seu tamanho. O script abaixo comprime cada uma com gzip, que é próximo do que trafega na rede, e devolve erro se alguma passar do limite.
// scripts/tamanho.js
const fs = require('fs');
const zlib = require('zlib');
const meta = JSON.parse(fs.readFileSync('meta.json', 'utf8'));
const LIMITE_GZIP = 150 * 1024;
let estourou = false;
for (const [arquivo, info] of Object.entries(meta.outputs)) {
if (!arquivo.endsWith('.js')) continue;
const gzip = zlib.gzipSync(fs.readFileSync(arquivo)).length;
console.log(arquivo, Math.round(info.bytes / 1024) + ' KB', 'gzip ' + Math.round(gzip / 1024) + ' KB');
if (gzip > LIMITE_GZIP) estourou = true;
}
process.exit(estourou ? 1 : 0);
Na Casa Pinho, a saída ficou assim (números do exemplo):
public/js/pedidos.js 402 KB gzip 96 KB
public/js/clientes.js 388 KB gzip 92 KB
public/js/relatorio.js 611 KB gzip 141 KB
O relatório pesa mais porque usa gráfico, e tudo bem: o peso agora tem motivo e endereço. O limite de 150 KB não é regra universal. É o número que a equipe combinou e que o pipeline cobra. Quando alguém importar o editor de texto na tela errada, o build reclama antes do cliente.
Quando o kit só oferece o combinador online
Em sistema antigo, às vezes a troca para npm não cabe neste mês. Dá para reduzir o estrago mesmo assim. Gere um pacote só com os componentes que as telas usam, salve ao lado dele um arquivo de texto com a versão do kit, a data e a lista exata do que foi marcado, e versione os dois juntos. Remova qualquer outra cópia da mesma biblioteca, seja de CDN ou de pasta antiga.
Na próxima atualização, refaça a seleção a partir dessa lista e teste as telas que usam o pacote antes de publicar. O combinador deixa de ser um ritual misterioso e vira um passo documentado, que outra pessoa consegue repetir.
Erros comuns
- Marcar tudo "para garantir": a página paga download e análise de código que nunca roda, e o tempo até a tela responder cresce no aparelho mais fraco.
- Arquivo gerado sem registro: ninguém sabe a versão nem os módulos, e a atualização vira tentativa e erro em produção.
- Cópia combinada e cópia do CDN na mesma página: duas versões disputam o mesmo global e o erro parece aleatório.
- Um pacote para o sistema inteiro: a tela de login baixa o gráfico do relatório, e qualquer mudança invalida o cache de todas as páginas.
- Build que só roda na máquina de uma pessoa: sem comando no
package.json, o artefato não é reproduzível e a correção urgente espera essa pessoa voltar. - Medir só uma vez: sem limite no pipeline, o pacote volta a engordar uma importação de cada vez.
Checklist
- Cada tela tem um arquivo de entrada que importa só os componentes que ela usa.
- A versão do kit está travada no lockfile.
- O comando de build está no
package.jsone roda numa máquina limpa. - Não há segunda cópia da mesma biblioteca em CDN ou pasta antiga.
- O painel Coverage mostra a maior parte do pacote em uso na tela correspondente.
- O tamanho comprimido de cada pacote é medido e tem limite no pipeline.
- Se a carga de dados falhar, a tela mostra uma mensagem legível.
Abra agora o maior arquivo JavaScript do seu sistema: você consegue listar, sem abrir o gerador, quais componentes estão dentro dele e em que versão?
Referência: https://csg.syncfusion.com/combine