A maioria das páginas da Web e aplicativos é composta de várias partes diferentes. Em vez de enviar todo o JavaScript que compõe o aplicativo assim que a primeira página é carregada, dividir o JavaScript em vários blocos melhora o desempenho da página.
Este codelab mostra como usar a divisão de código para melhorar o desempenho de um aplicativo simples que classifica três números.
Medir
Como sempre, é importante primeiro medir o desempenho de um site antes de tentar adicionar otimizações.
- Para visualizar o site, pressione Ver app e depois Tela cheia
.
- Pressione "Control+Shift+J" (ou "Command+Option+J" no Mac) para abrir o DevTools.
- Clique na guia Rede.
- Marque a caixa de seleção Desativar cache.
- Recarregue o app.
71,2 KB de JavaScript apenas para classificar alguns números em um aplicativo simples. What gives?
No código-fonte (src/index.js
), a biblioteca lodash
é importada e usada
neste aplicativo. O Lodash oferece muitas funções de utilidade
úteis, mas apenas um método do pacote está sendo usado aqui.
Instalar e importar dependências inteiras de terceiros quando apenas uma pequena parte delas está sendo usada é um erro comum.
Otimizar
Há algumas maneiras de reduzir o tamanho do pacote:
- Escrever um método de classificação personalizado em vez de importar uma biblioteca de terceiros
- Use o método
Array.prototype.sort()
integrado para classificar numericamente - Importe apenas o método
sortBy
delodash
, não a biblioteca inteira. - Baixe o código para classificação somente quando o usuário clicar no botão.
As opções 1 e 2 são métodos perfeitamente adequados para reduzir o tamanho do pacote e provavelmente seriam as mais adequadas para um aplicativo real. No entanto, eles não são usados neste tutorial para fins de ensino 😈.
As opções 3 e 4 ajudam a melhorar o desempenho desse aplicativo. As próximas seções deste codelab abordam essas etapas. Como em qualquer tutorial de programação, tente sempre escrever o código por conta própria em vez de copiar e colar.
Importe apenas o que você precisa
Alguns arquivos precisam ser modificados para importar apenas o método único de lodash
.
Para começar, substitua esta dependência em package.json
:
"lodash": "^4.7.0",
com este código:
"lodash.sortby": "^4.7.0",
Agora, em src/index.js
, importe este módulo específico:
import "./style.css";
import _ from "lodash";
import sortBy from "lodash.sortby";
E atualize a forma como os valores são classificados::
form.addEventListener("submit", e => {
e.preventDefault();
const values = [input1.valueAsNumber, input2.valueAsNumber, input3.valueAsNumber];
const sortedValues = _.sortBy(values);
const sortedValues = sortBy(values);
results.innerHTML = `
<h2>
${sortedValues}
</h2>
`
});
Atualize o aplicativo, abra o DevTools e confira o painel Rede novamente.
Para esse aplicativo, o tamanho do pacote foi reduzido em mais de quatro vezes com muito pouco trabalho, mas ainda há espaço para melhorias.
Divisão de código
O webpack é um dos bundlers de módulos de código aberto mais usados atualmente. Em resumo, ele agrupa todos os módulos JavaScript (e outros recursos) que compõem um aplicativo da Web em arquivos estáticos que podem ser lidos pelo navegador.
O único pacote usado neste aplicativo pode ser dividido em dois blocos separados:
- Um responsável pelo código que compõe nossa rota inicial
- Um bloco secundário que contém nosso código de classificação
Com o uso de importações dinâmicas, um trecho secundário pode ser carregado de forma lenta ou carregado sob demanda. Neste aplicativo, o código que compõe o trecho só pode ser carregado quando o usuário pressiona o botão.
Comece removendo a importação de nível superior do método de classificação em src/index.js
:
import sortBy from "lodash.sortby";
E importe-o no listener de eventos que é acionado quando o botão é pressionado:
form.addEventListener("submit", e => {
e.preventDefault();
import('lodash.sortby')
.then(module => module.default)
.then(sortInput())
.catch(err => { alert(err) });
});
O recurso import()
faz parte de uma proposta (atualmente na fase 3 do processo TC39) para incluir a capacidade de importar um módulo dinamicamente. O webpack já incluiu suporte para isso e segue a mesma sintaxe estabelecida pela proposta.
import()
retorna uma promessa e, quando ela é resolvida, o módulo selecionado é fornecido e dividido em um trecho separado. Depois que o módulo é
retornado, module.default
é usado para referenciar a exportação
padrão fornecida pelo lodash. A promessa é encadeada com outra .then
que
chama um método sortInput
para classificar os três valores de entrada. No final da cadeia de promessas, .catch()
é usado para processar casos em que a promessa é rejeitada
devido a um erro.
A última coisa que precisa ser feita é escrever o método sortInput
no
final do arquivo. Ela precisa retornar uma função que
recebe o método importado de lodash.sortBy
. A função aninhada pode então
classificar os três valores de entrada e atualizar o DOM.
const sortInput = () => {
return (sortBy) => {
const values = [
input1.valueAsNumber,
input2.valueAsNumber,
input3.valueAsNumber
];
const sortedValues = sortBy(values);
results.innerHTML = `
<h2>
${sortedValues}
</h2>
`
};
}
Monitoramento
Atualize o aplicativo pela última vez e fique de olho no painel Rede novamente. Apenas um pequeno pacote inicial é baixado assim que o app é carregado.
Depois que o botão é pressionado para classificar os números de entrada, o bloco que contém o código de classificação é buscado e executado.
Observe como os números ainda são classificados.
Conclusão
A divisão de código e o carregamento lento podem ser técnicas extremamente úteis para reduzir o tamanho inicial do pacote do aplicativo, o que pode resultar diretamente em tempos de carregamento de página muito mais rápidos. No entanto, há algumas coisas importantes que precisam ser consideradas antes de incluir essa otimização no seu aplicativo.
Interface de carregamento lento
Ao carregar módulos específicos de código de forma lenta, é importante considerar como seria a experiência para usuários com conexões de rede mais fracas. Dividir e carregar um bloco de código muito grande quando um usuário envia uma ação pode fazer com que pareça que o aplicativo parou de funcionar. Por isso, considere mostrar um indicador de carregamento de algum tipo.
Carregamento lento de módulos de nós de terceiros
Nem sempre é a melhor abordagem carregar dependências de terceiros de forma lenta no seu
aplicativo, e isso depende de onde você as usa. Normalmente, as dependências de terceiros são divididas em um pacote vendor
separado que pode ser armazenado em cache, já que não são atualizadas com tanta frequência. Leia mais sobre como o
SplitChunksPlugin pode
ajudar você a fazer isso.
Carregamento lento com um framework JavaScript
Muitos frameworks e bibliotecas conhecidos que usam o webpack oferecem abstrações para facilitar o carregamento lento em vez de usar importações dinâmicas no meio do aplicativo.
- Módulos de carregamento lento com Angular
- Divisão de código com o React Router
- Carregamento lento com o Vue Router
Embora seja útil entender como as importações dinâmicas funcionam, sempre use o método recomendado pelo framework/biblioteca para carregar módulos específicos de forma lenta.
Pré-carregamento e pré-busca
Sempre que possível, aproveite as dicas do navegador, como <link rel="preload">
ou <link rel="prefetch">
, para tentar carregar módulos essenciais ainda mais rápido. O webpack oferece suporte a ambas as dicas usando comentários mágicos em instruções de importação. Isso é explicado com mais detalhes no guia Pré-carregar partes essenciais.
Carregamento lento além do código
As imagens podem constituir uma parte significativa de um aplicativo. O carregamento lento daqueles que estão abaixo da dobra ou fora da janela de visualização do dispositivo pode acelerar um site. Leia mais sobre isso no guia Lazysizes.