Este codelab mostra como reduzir e compactar o código para o seguinte aplicativo melhora o desempenho da página reduzindo tamanho da solicitação do app.
Medir
Antes de começar a incluir as otimizações, é sempre uma boa ideia analisar primeiro o estado atual do aplicativo.
- Para visualizar o site, pressione Ver app. Em seguida, pressione Tela cheia
Esse app, que também foi abordado no artigo Remover itens code", permite votar no seu favorito gatinho. 🐈
Agora confira o tamanho do aplicativo:
- 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.
- Atualize o app.
Embora muito progresso tenha sido feito na etapa "Remover código não utilizado" codelab para reduzir o tamanho desse pacote. 225 KB ainda é muito grande.
Minificação
Considere o bloco de código a seguir.
function soNice() {
let counter = 0;
while (counter < 100) {
console.log('nice');
counter++;
}
}
Se essa função for salva em um arquivo próprio, o tamanho do arquivo será de cerca de 112 bytes (bytes).
Se todos os espaços em branco forem removidos, o código resultante será parecido com este:
function soNice(){let counter=0;while(counter<100){console.log("nice");counter++;}}
O tamanho do arquivo seria de cerca de 83 B. Se ficar ainda mais danificado, reduzindo o comprimento do nome da variável e modificando algumas expressões, o código final pode acabam ficando assim:
function soNice(){for(let i=0;i<100;)console.log("nice"),i++}
O tamanho do arquivo agora atinge 62 B.
A cada etapa, o código fica mais difícil de ler. No entanto, a configuração O mecanismo JavaScript interpreta cada um deles da mesma forma. A benefício de ofuscar o código dessa maneira pode ajudar a obter arquivos menores tamanhos. 112 bilhões não eram muito para começar, mas ainda havia um percentual de 50% redução de tamanho!
Neste aplicativo, a versão 4 do webpack é usada como
bundler de módulo. A versão específica pode ser encontrada em package.json
.
"devDependencies": {
//...
"webpack": "^4.16.4",
//...
}
A versão 4 já reduz o pacote por padrão durante o modo de produção. Ela usa
TerserWebpackPlugin
é um plug-in para Terser.
Terser é uma ferramenta popular usada para compactar código JavaScript.
Para ter uma ideia da aparência do código minimizado, clique em
main.bundle.js
enquanto ainda estiver no painel Network do DevTools. Agora clique no
guia Resposta.
O código na forma final, minificado e corrompido, é mostrado no corpo da resposta.
Para descobrir qual seria o tamanho do pacote se não tiver sido minificado, abra
webpack.config.js
e atualize a configuração de mode
.
module.exports = {
mode: 'production',
mode: 'none',
//...
Atualize o aplicativo e confira o tamanho do pacote novamente no Painel Network do DevTools
É uma grande diferença! 😅
Reverta as mudanças aqui antes de continuar.
module.exports = {
mode: 'production',
mode: 'none',
//...
A inclusão de um processo para reduzir código no seu aplicativo depende das ferramentas que você usa:
- Se o webpack v4 ou superior for usado, nenhum trabalho adicional precisará ser feito já que o código é minificado por padrão no modo de produção. 👍
- Se uma versão mais antiga do webpack for usada, instale e inclua
TerserWebpackPlugin
no processo de compilação do webpack. A documentação explica isso em detalhes. - Outros plug-ins de minificação também existem e podem ser usados no lugar deles, como BabelMinifyWebpackPlugin e ClosureCompilerPlugin.
- Se um bundler de módulo não estiver sendo usado, use Terser. como uma ferramenta da CLI ou incluí-lo diretamente como uma dependência.
Compactação
Embora o termo "compactação" é usado vagamente para explicar como o código é reduzidos durante o processo de minificação, eles não são realmente comprimidos sentido literal.
A compactação geralmente se refere ao código que foi modificado usando uma algoritmo de compactação. Ao contrário da minificação, que acaba fornecendo válido, o código compactado precisa ser descompactado antes de ser usado.
A cada solicitação e resposta HTTP, os navegadores e servidores da Web podem adicionar
cabeçalhos para incluir
informações adicionais sobre o recurso buscado ou recebido. Isso pode ser
na guia Headers
do painel "Network do DevTools", em que três tipos
são mostrados:
- General representa cabeçalhos gerais relevantes para toda a solicitação/resposta interação.
- Cabeçalhos de resposta mostra uma lista de cabeçalhos específicos da resposta real do servidor.
- Cabeçalhos de solicitação mostra uma lista de cabeçalhos anexados à solicitação pelo para o cliente.
Observe o cabeçalho accept-encoding
no Request Headers
.
accept-encoding
é usado pelo navegador para especificar qual conteúdo
formatos de codificação e de compactação compatíveis. Existem várias
algoritmos de compactação de texto, mas existem apenas três que são
suportados aqui para a compactação (e descompactação) de solicitações de rede HTTP:
- Gzip (
gzip
): a compactação mais usada. para interações entre servidor e cliente. Ele se baseia no Deflate algoritmo conhecido e é compatível com todos os navegadores atuais. - Deflate (
deflate
): não é usado com frequência. - Brotli (
br
): uma compactação mais recente. algoritmo que visa melhorar ainda mais as taxas de compactação, o que pode resultar em carregamentos de página ainda mais rápidos. Ele é suportado no versões mais recentes da maioria dos navegadores.
O aplicativo de exemplo neste tutorial é idêntico ao aplicativo concluído no Codelab "Remover código não utilizado", exceto pelo fato de que O Express agora é usado como um framework de servidor. Nos próximos algumas seções, vamos conhecer a compactação estática e dinâmica.
Compactação dinâmica
A compactação dinâmica envolve a compactação de recursos em tempo real à medida que eles são solicitado pelo navegador.
Prós
- A criação e a atualização de versões compactadas salvas de recursos não precisam ser feito.
- A compactação em tempo real funciona especialmente bem para páginas da Web que são geradas de modo dinâmico.
Contras
- Compactação de arquivos em níveis mais altos para obter taxas de compactação melhores. demora mais. Isso pode causar um impacto na performance enquanto o usuário espera os recursos compactadas antes de serem enviadas pelo servidor.
Compactação dinâmica com o Node/Express
O arquivo server.js
é responsável por configurar o servidor do nó que hospeda
o aplicativo.
const express = require('express');
const app = express();
app.use(express.static('public'));
const listener = app.listen(process.env.PORT, function() {
console.log('Your app is listening on port ' + listener.address().port);
});
No momento, tudo o que isso faz é importar express
e usar o express.static
middleware para carregar todos os arquivos estáticos HTML, JS e CSS na
public/
(e esses arquivos são criados pelo webpack em cada build).
Para garantir que todos os recursos sejam compactados sempre que forem solicitados, o
compression pode
ser usados. Para começar, adicione-o como um devDependency
no package.json
:
"devDependencies": {
//...
"compression": "^1.7.3"
},
E importe-o para o arquivo do servidor, server.js
:
const express = require('express');
const compression = require('compression');
E adicione-o como um middleware antes de express.static
ser ativado:
//...
const app = express();
app.use(compression());
app.use(express.static('public'));
//...
Agora atualize o app e confira o tamanho do pacote no painel Network.
De 225 KB a 61,6 KB! No Response Headers
agora, um content-encoding
mostra que o servidor está enviando esse arquivo codificado com gzip
.
Compactação estática
A ideia por trás da compactação estática é ter os recursos compactados e salvos com antecedência.
Prós
- A latência devido aos altos níveis de compactação não é mais uma preocupação. Nada precisa acontecer imediatamente para compactar arquivos, pois agora eles podem ser obtidos diretamente.
Contras
- Os recursos precisam ser compactados em cada build. Os tempos de build podem aumentar significativamente se altos níveis de compactação forem usados.
Compactação estática com o Node/Express e o webpack
Como a compactação estática envolve a compactação de arquivos antecipadamente, o webpack
podem ser modificadas para compactar recursos como parte da etapa de criação.
CompressionPlugin
pode ser usada para isso.
Para começar, adicione-o como um devDependency
no package.json
:
"devDependencies": {
//...
"compression-webpack-plugin": "^1.1.11"
},
Como qualquer outro plug-in do webpack, importe-o no arquivo de configurações,
webpack.config.js:
const path = require("path");
//...
const CompressionPlugin = require("compression-webpack-plugin");
E inclua-o na matriz plugins
:
module.exports = {
//...
plugins: [
//...
new CompressionPlugin()
]
}
Por padrão, o plug-in compacta os arquivos de build usando gzip
. Dê uma olhada
na documentação
para saber como adicionar opções para usar um algoritmo diferente ou incluir/excluir
determinados arquivos.
Quando o aplicativo é recarregado e criado novamente, uma versão compactada do pacote principal é
foi criado. Abra o Glitch Console para ver o que tem dentro do
public/
final exibido pelo servidor do nó.
- Clique no botão Ferramentas.
- Clique no botão Console.
- No console, execute os comandos a seguir para mudar para
public
e confira todos os seus arquivos:
cd public
ls
A versão compactada em gzip do pacote, main.bundle.js.gz
, agora está salva aqui como
muito bem. CompressionPlugin
também compacta index.html
por padrão.
A próxima etapa é pedir para o servidor enviar esses arquivos
sempre que suas versões JS originais forem solicitadas. Isso pode ser feito
definindo uma nova rota em server.js
antes que os arquivos sejam disponibilizados com
express.static
.
const express = require('express'); const app = express(); app.get('*.js', (req, res, next) => { req.url = req.url + '.gz'; res.set('Content-Encoding', 'gzip'); next(); }); app.use(express.static('public')); //...
app.get
é usada para informar ao servidor como responder a uma solicitação GET para um
em um endpoint específico. Uma função de callback é usada para definir como lidar com o
solicitação. O trajeto funciona assim:
- Especificar
'*.js'
como o primeiro argumento significa que ele funciona para cada que é disparado para buscar um arquivo JS. - No callback,
.gz
é anexado ao URL da solicitação e ao O cabeçalho de respostaContent-Encoding
está definido comogzip
. - Por fim,
next()
garante que a sequência continue para qualquer callback que podem vir a seguir.
Quando o app for atualizado, confira o painel Network
mais uma vez.
Assim como antes, uma redução significativa no tamanho dos pacotes.
Conclusão
Este codelab abordou o processo de minificação e compactação do código-fonte. Ambas as técnicas estão se tornando padrão em muitas das ferramentas por isso, é importante descobrir se o conjunto de ferramentas já ou se você deve começar a aplicar os dois processos por conta própria.