Este codelab é uma extensão do codelab
Minify and compress network payloads
e pressupõe que você conheça os conceitos básicos de compactação. Em
comparação com outros algoritmos de compactação, como gzip
, este codelab explora como
a compactação Brotli (br
) pode reduzir ainda mais as taxas de compactação e o tamanho
geral do app.
Medir
Antes de adicionar otimizações, é sempre recomendável analisar o estado atual do aplicativo.
- Clique em Remix to Edit para tornar o projeto editável.
- Para visualizar o site, pressione View App. Em seguida, pressione Fullscreen .
No codelab anterior sobre como minificar e compactar payloads de rede,
reduzimos o tamanho de main.js
de 225 KB para 61,6 KB. Neste codelab, você
vai descobrir como a compactação Brotli pode reduzir ainda mais o tamanho do pacote.
Compactação Brotli
Brotli
é um algoritmo de compactação mais recente que pode oferecer resultados de compactação de texto
ainda melhores do que gzip
. De acordo com o
CertSimple, a performance do Brotli é:
- 14% menor que
gzip
para JavaScript - 21% menor que
gzip
para HTML - 17% menor que
gzip
para CSS
Para usar o Brotli, seu servidor precisa oferecer suporte a HTTPS. O Brotli é compatível com todos
os navegadores modernos. Os navegadores compatíveis com Brotli
incluem br
nos cabeçalhos Accept-Encoding
:
Accept-Encoding: gzip, deflate, br
É possível determinar qual algoritmo de compactação é usado usando o
campo Content-Encoding
na guia "Rede" das Ferramentas para Desenvolvedores do Chrome
(Command+Option+I
ou Ctrl+Alt+I
):
Como ativar o Brotli
A forma de configurar um servidor da Web para enviar recursos codificados em Brotli depende de como você planeja codificá-los. Você pode compactar os recursos dinamicamente com o Brotli no momento da solicitação (dinâmico) ou codificá-los com antecedência para que eles já estejam compactados quando o usuário solicitar (estático).
Compactação dinâmica
A compactação dinâmica envolve a compactação de recursos em tempo real conforme eles são solicitados pelo navegador.
Vantagens
- Não é necessário criar e atualizar versões compactadas salvas de recursos.
- A compactação on-the-fly funciona muito bem para páginas da Web geradas dinamicamente.
Desvantagens
- A compactação de arquivos em níveis mais altos para alcançar melhores proporções de compactação leva mais tempo. Isso pode causar uma queda de desempenho, já que o usuário espera que os recursos sejam compactados antes de serem enviados pelo servidor.
Compactação dinâmica com Node e Express
O arquivo server.js
é responsável por configurar o servidor Node 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}`);
});
Isso importa express
e usa o middleware express.static
para carregar todos os arquivos estáticos de HTML, JS e CSS no
public/directory
. Esses arquivos são criados pelo webpack em cada build.
Para garantir que todos os recursos sejam compactados usando brotli sempre que forem
solicitados, o módulo shrink-ray
pode ser usado. Comece adicionando-o como um devDependency
em package.json
:
"devDependencies": {
// ...
"shrink-ray": "^0.1.3"
},
E importe-o para o arquivo do servidor, server.js
:
const express = require('express');
const shrinkRay = require('shrink-ray');
E adicione como um middleware antes que express.static
seja montado:
// ...
const app = express();
// Compress all requests
app.use(shrinkRay());
app.use(express.static('public'));
Agora, recarregue o app e confira o tamanho do pacote no painel "Rede":
Agora você pode ver que brotli
é aplicado a partir de bz
no cabeçalho Content-Encoding
.
O main.bundle.js
foi reduzido de 225 KB para 53,1 KB. Isso é cerca de 14% menor
em comparação com gzip
(61,6 KB).
Compactação estática
A ideia por trás da compactação estática é ter recursos compactados e salvos com antecedência.
Vantagens
- A latência devido a níveis altos de compactação não é mais um problema. Nada precisa acontecer em tempo real para compactar arquivos, já que eles podem ser buscados diretamente.
Desvantagens
- Os recursos precisam ser compactados em cada build. Os tempos de build podem aumentar significativamente se níveis de compactação altos forem usados.
Compressão estática com Node e Express com webpack
Como a compactação estática envolve a compactação de arquivos com antecedência, as configurações do webpack
podem ser modificadas para compactar recursos como parte da etapa de build. O
brotli-webpack-plugin
pode ser usado para isso.
Comece adicionando-o como um devDependency
em package.json
:
"devDependencies": {
// ...
"brotli-webpack-plugin": "^1.1.0"
},
Como qualquer outro plug-in do webpack, importe-o no arquivo de configurações,
webpack.config.js
:
var path = require("path");
//...
var BrotliPlugin = require('brotli-webpack-plugin');
E inclua na matriz de plug-ins:
module.exports = {
// ...
plugins: [
// ...
new BrotliPlugin({
asset: '[file].br',
test: /\.(js)$/
})
]
},
A matriz do plug-in usa os seguintes argumentos:
asset
: o nome do recurso de destino.[file]
é substituído pelo nome do arquivo de recurso original.test
: todos os recursos que correspondem a essa RegExp (ou seja, recursos JavaScript que terminam em.js
) são processados.
Por exemplo, main.js
seria renomeado como main.js.br
.
Quando o app é recarregado e recriado, uma versão compactada do pacote principal é
criada. Abra o Glitch Console para conferir o que está dentro do diretório
public/
final que é servido pelo servidor Node.
- Clique no botão Ferramentas.
- Clique no botão Console.
- No console, execute os comandos abaixo para mudar para o diretório
public
e conferir todos os arquivos:
cd public
ls -lh
A versão compactada do pacote, main.bundle.js.br
, agora é salva
neste local e é cerca de 76% menor (225 KB em comparação com 53 KB) do que
main.bundle.js
.
Em seguida, diga ao servidor para enviar esses arquivos compactados com brotli sempre que as
versões originais do JS estiverem sendo solicitadas. Isso pode ser feito definindo uma nova
rota em server.js
antes que os arquivos sejam veiculados com express.static
.
const express = require('express');
const app = express();
app.get('*.js', (req, res, next) => {
req.url = req.url + '.br';
res.set('Content-Encoding', 'br');
res.set('Content-Type', 'application/javascript; charset=UTF-8');
next();
});
app.use(express.static('public'));
app.get
é usado para informar ao servidor como responder a uma solicitação GET
para um
endpoint específico. Uma função de callback é usada para definir como processar essa
solicitação. O trajeto funciona assim:
- Especificar
'*.js'
como o primeiro argumento significa que isso funciona para todos os endpoints acionados para buscar um arquivo JS. - No callback,
.br
é anexado ao URL da solicitação, e o cabeçalho de respostaContent-Encoding
é definido comobr
. - O cabeçalho
Content-Type
é definido comoapplication/javascript; charset=UTF-8
para especificar o tipo MIME. - Por fim,
next()
garante que a sequência continue para qualquer callback que possa ser o próximo.
Como alguns navegadores podem não oferecer suporte à compactação Brotli, confirme se o Brotli é
compatível antes de retornar o arquivo compactado com Brotli verificando se o
cabeçalho de solicitação Accept-Encoding
inclui br
:
const express = require('express');
const app = express();
app.get('*.js', (req, res, next) => {
if (req.header('Accept-Encoding').includes('br')) {
req.url = req.url + '.br';
console.log(req.header('Accept-Encoding'));
res.set('Content-Encoding', 'br');
res.set('Content-Type', 'application/javascript; charset=UTF-8');
}
next();
});
app.use(express.static('public'));
Quando o app for recarregado, confira o painel de rede novamente.
Pronto. Você usou a compactação Brotli para compactar ainda mais seus recursos.
Conclusão
Este codelab ilustra como brotli
pode reduzir ainda mais o tamanho
geral do app. Quando houver suporte, brotli
é um algoritmo de compactação mais eficiente do que
gzip
.