Minimizza e comprimi i payload di rete con Brotli

Michele Di Blasio
Michael DiBlasio

Questo codelab è un'estensione del codelab per minimizzare e comprimere i payload di rete e presuppone che tu abbia familiarità con i concetti di base della compressione. Rispetto ad altri algoritmi di compressione come gzip, questo codelab esamina in che modo la compressione Brotli può ridurre ulteriormente i rapporti di compressione e le dimensioni complessive della tua app.

Screenshot dell'app

Misura

Prima di addentrarci nelle ottimizzazioni, è sempre opportuno analizzare lo stato attuale dell'applicazione.

  1. Fai clic su Remix per modificare per rendere il progetto modificabile.
  2. Per visualizzare l'anteprima del sito, premi Visualizza app, quindi Schermo intero schermo intero.

Nel precedente codelab per minimizzare e comprimere i payload di rete, abbiamo ridotto le dimensioni di main.js da 225 kB a 61,6 kB. In questo codelab, vedrai in che modo la compressione di Brotli può ridurre ulteriormente le dimensioni del bundle.

Compressione Brotli

Brotli è un algoritmo di compressione più recente che può fornire risultati di compressione del testo ancora migliori rispetto a gzip. In base a CertSimple, il rendimento di Brotli è:

  • Minore del 14% rispetto a gzip per JavaScript
  • Minore del 21% rispetto a gzip per HTML
  • Minore del 17% rispetto a gzip per CSS

Per utilizzare Brotli, il tuo server deve supportare HTTPS. Brotli è supportato nelle versioni più recenti della maggior parte dei browser. I browser che supportano Brotli includeranno br nelle intestazioni Accept-Encoding:

Accept-Encoding: gzip, deflate, br

Puoi determinare quale algoritmo di compressione viene utilizzato tramite il campo Content-Encoding nella scheda Rete degli Strumenti per sviluppatori di Chrome (Command+Option+I o Ctrl+Alt+I):

Riquadro Network

Attivazione di Brotli

Compressione dinamica

La compressione dinamica comporta la compressione all'istante degli asset quando vengono richiesti dal browser.

Vantaggi

  • Non è necessario creare e aggiornare le versioni compresse salvate degli asset.
  • La compressione immediata funziona soprattutto per le pagine web generate dinamicamente.

Svantaggi

  • La compressione dei file a livelli più elevati per ottenere rapporti di compressione migliori richiede più tempo. Di conseguenza, l'utente attende che gli asset vengano compressi prima che vengano inviati dal server.

Compressione dinamica con Node/Express

Il file server.js è responsabile della configurazione del server nodo che ospita l'applicazione.

var express = require('express');

var app = express();

app.use(express.static('public'));

var listener = app.listen(process.env.PORT, function() {
  console.log('Your app is listening on port ' + listener.address().port);
});

Al momento è sufficiente importare express e utilizzare il middleware express.static per caricare tutti i file HTML, JS e CSS statici in public/directory (i file vengono creati dal webpack ad ogni build).

Per assicurarti che tutti gli asset vengano compressi utilizzando Brotli ogni volta che vengono richiesti, è possibile utilizzare il modulo shrink-ray. Inizia aggiungendolo come devDependency in package.json:

"devDependencies": {
  //...
  "shrink-ray": "^0.1.3"
},

e importalo nel file del server, server.js:

var express = require('express');
var shrinkRay = require('shrink-ray');

Aggiungilo come middleware prima che venga montato express.static:

//...
var app = express();

// compress all requests
app.use(shrinkRay());

app.use(express.static('public'));

Ora ricarica l'app e dai un'occhiata alle dimensioni del bundle nel riquadro Network:

Dimensioni del bundle con compressione Brotli dinamica

Ora puoi vedere che l'impostazione brotli è applicata da bz nell'intestazione Content-Encoding. main.bundle.js ridotto da 225 kB a 53,1 kB. Si tratta di un valore inferiore di circa il 14% rispetto a gzip (61,6 kB).

Compressione statica

L'idea alla base della compressione statica è fare in modo che gli asset vengano compressi e salvati in anticipo.

Vantaggi

  • La latenza dovuta a livelli di compressione elevati non è più un problema. Non è necessario comprimere i file sul momento, dato che ora possono essere recuperati direttamente.

Svantaggi

  • Gli asset devono essere compressi a ogni build. I tempi di compilazione possono aumentare significativamente se vengono utilizzati livelli di compressione elevati.

Compressione statica con Node/Express e webpack

Poiché la compressione statica comporta la compressione in anticipo dei file, le impostazioni del webpack possono essere modificate per comprimere gli asset nell'ambito del passaggio di creazione. A questo scopo, è possibile usare l'elemento brotli-webpack-plugin.

Inizia aggiungendolo come devDependency in package.json:

"devDependencies": {
  //...
 "brotli-webpack-plugin": "^1.1.0"
},

Come qualsiasi altro plug-in webpack, importalo nel file di configurazione, webpack.config.js:

var path = require("path");

//...
var BrotliPlugin = require('brotli-webpack-plugin');

Includilo nell'array dei plug-in:

module.exports = {
  // ...
  plugins: [
    // ...
    new BrotliPlugin({
      asset: '[file].br',
      test: /\.(js)$/
    })
  ]
},

L'array di plug-in utilizza i seguenti argomenti:

  • asset: il nome dell'asset target.
  • [file] viene sostituito con il nome del file dell'asset originale.
  • test: vengono elaborati tutti gli asset che corrispondono a questa espressione regolare (ovvero gli asset JavaScript che terminano con .js).

Ad esempio, main.js verrebbe rinominato in main.js.br.

Quando l'app si ricarica e ricrea, viene creata una versione compressa del bundle principale. Apri la console Glitch per dare un'occhiata ai contenuti della directory public/ finale gestita dal server Node.

  1. Fai clic sul pulsante Strumenti.
  2. Fai clic sul pulsante Console.
  3. Nella console, esegui questi comandi per passare alla directory public e visualizzare tutti i relativi file:
cd public
ls -lh
Dimensioni del bundle con compressione Brotli statica

Anche la versione compressa del bundle, main.bundle.js.br, viene salvata qui e ha dimensioni inferiori di circa il 76% (225 kB rispetto a 53 kB) rispetto a main.bundle.js.

Successivamente, comunica al server di inviare questi file compressi ogni volta che vengono richieste le versioni JS originali. Per farlo, definisci un nuovo percorso in server.js prima che i file vengano pubblicati con express.static.

var express = require('express');

var 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 viene utilizzato per indicare al server come rispondere a una richiesta GET per un endpoint specifico. Viene quindi utilizzata una funzione di callback per definire come gestire questa richiesta. Il percorso funziona nel seguente modo:

  • Se specifichi '*.js' come primo argomento, questo funziona per ogni endpoint attivato per recuperare un file JS.
  • All'interno del callback, .br è associato all'URL della richiesta e l'intestazione della risposta Content-Encoding è impostata su br.
  • L'intestazione Content-Type è impostata su application/javascript; charset=UTF-8 per specificare il tipo MIME.
  • Infine, next() assicura che la sequenza continui a ogni callback successivo.

Poiché alcuni browser potrebbero non supportare la compressione brotli, verifica che quest'ultimo sia supportato prima di restituire il file compresso controllando che l'intestazione della richiesta Accept-Encoding includa br:

var express = require('express');

var 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'));

Una volta ricaricata l'app, dai un'altra occhiata al riquadro Rete.

Dimensione bundle 53,1 kB (da 225 kB)

Success! Hai utilizzato la compressione Brotli per comprimere ulteriormente gli asset.

Conclusione

Questo codelab ha mostrato in che modo brotli può ridurre ulteriormente le dimensioni complessive della tua app. Se supportato, brotli è un algoritmo di compressione più potente di gzip.