Réduire et compresser les charges utiles du réseau avec des brotli

Michael DiBlasio
Michael DiBlasio

Cet atelier de programmation est une extension de l'atelier de programmation "Réduire et compresser les charges utiles réseau" et suppose que vous connaissez les concepts de base de la compression. Par rapport à d'autres algorithmes de compression tels que gzip, cet atelier de programmation explore comment la compression Brotli peut réduire davantage les taux de compression et la taille globale de votre application.

Capture d'écran de l'application

Mesurer

Avant de vous lancer dans l'ajout d'optimisations, il est toujours judicieux d'analyser d'abord l'état actuel de l'application.

  1. Cliquez sur Remix to Edit (Remixer pour modifier) pour pouvoir modifier le projet.
  2. Pour prévisualiser le site, appuyez sur View App (Afficher l'application), puis sur Fullscreen (Plein écran) plein écran.

Dans l'atelier de programmation précédent Réduire et compresser les charges utiles réseau, nous avons réduit la taille de main.js, passant de 225 Ko à 61,6 Ko. Dans cet atelier de programmation, vous découvrirez comment la compression Brotli peut réduire encore plus la taille du bundle.

Compression brotli

Brotli est un algorithme de compression plus récent qui peut fournir des résultats de compression de texte encore meilleurs que gzip. Selon CertSimple, les performances de Brotli sont les suivantes:

  • 14% inférieure à gzip pour JavaScript
  • 21% inférieure à gzip pour le format HTML
  • 17% inférieure à gzip pour le CSS

Pour que vous puissiez utiliser Brotli, votre serveur doit être compatible avec le protocole HTTPS. Brotli est compatible avec les dernières versions de la plupart des navigateurs. Les navigateurs compatibles avec Brotli incluent br dans les en-têtes Accept-Encoding:

Accept-Encoding: gzip, deflate, br

Vous pouvez déterminer l'algorithme de compression utilisé dans le champ Content-Encoding de l'onglet "Réseau" des outils pour les développeurs Chrome (Command+Option+I ou Ctrl+Alt+I):

Panneau "Network" (Réseau)

Activer Brotli

Compression dynamique

La compression dynamique consiste à compresser les éléments à la volée, à mesure qu'ils sont demandés par le navigateur.

Avantages

  • Il n'est pas nécessaire de créer et de mettre à jour des versions compressées enregistrées des éléments.
  • La compression à la volée fonctionne particulièrement bien pour les pages Web générées dynamiquement.

Inconvénients

  • La compression des fichiers à des niveaux supérieurs pour obtenir de meilleurs taux de compression prend plus de temps. Cela peut entraîner une perte de performances, car l'utilisateur attend que les éléments soient compressés avant qu'ils ne soient envoyés par le serveur.

Compression dynamique avec Node/Express

Le fichier server.js est responsable de la configuration du serveur de nœuds qui héberge l'application.

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);
});

Actuellement, il s'agit d'importer express et d'utiliser le middleware express.static pour charger tous les fichiers HTML, JavaScript et CSS statiques dans public/directory (ces fichiers sont créés par webpack à chaque compilation).

Pour vous assurer que tous les éléments sont compressés à l'aide de Brotli à chaque requête, vous pouvez utiliser le module shrink-ray. Commencez par l'ajouter en tant que devDependency dans package.json:

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

Importez-le ensuite dans le fichier serveur server.js:

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

Ajoutez-le en tant qu'intergiciel avant l'installation de express.static:

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

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

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

Actualisez l'application et examinez la taille du bundle dans le panneau "Network" :

Taille du bundle avec compression dynamique Brotli

Vous pouvez voir que brotli est appliqué à partir de bz dans l'en-tête Content-Encoding. main.bundle.js est passé de 225 Ko à 53,1 Ko. Elle est environ 14% plus petite que gzip (61,6 Ko).

Compression statique

L'idée derrière la compression statique est de compresser et d'enregistrer les éléments à l'avance.

Avantages

  • La latence due à des niveaux de compression élevés n'est plus une préoccupation. Rien ne doit se produire à la volée pour compresser les fichiers, car ils peuvent désormais être récupérés directement.

Inconvénients

  • Les éléments doivent être compressés à chaque compilation. Les durées de compilation peuvent augmenter considérablement si des niveaux de compression élevés sont utilisés.

Compression statique avec Node/Express et webpack

Étant donné que la compression statique implique la compression de fichiers à l'avance, les paramètres webpack peuvent être modifiés pour compresser les éléments dans le cadre de l'étape de compilation. Pour ce faire, vous pouvez utiliser brotli-webpack-plugin.

Commencez par l'ajouter en tant que devDependency dans package.json:

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

Comme pour tout autre plug-in webpack, importez-le dans le fichier de configuration webpack.config.js:

var path = require("path");

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

Et incluez-le dans le tableau de plugins:

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

Le tableau de plug-ins utilise les arguments suivants:

  • asset: nom de l'élément cible.
  • [file] est remplacé par le nom de fichier d'origine de l'élément.
  • test: tous les éléments correspondant à cette expression régulière (c'est-à-dire les éléments JavaScript se terminant par .js) sont traités.

Par exemple, main.js sera renommé main.js.br.

Lorsque l'application est actualisée et recréée, une version compressée du bundle principal est créée. Ouvrez la console Glitch pour examiner le contenu du répertoire public/ final diffusé par le serveur Node.

  1. Cliquez sur le bouton Tools (Outils).
  2. Cliquez sur le bouton Console.
  3. Dans la console, exécutez les commandes suivantes pour accéder au répertoire public et afficher tous ses fichiers:
cd public
ls -lh
Taille du faisceau avec compression statique de Brotli

La version compressée au format Brotli du bundle, main.bundle.js.br, est désormais également enregistrée ici et a une taille inférieure d'environ 76% (225 Ko contre 53 Ko) à celle de main.bundle.js.

Indiquez ensuite au serveur d'envoyer ces fichiers compressés en mode Brotli chaque fois que leurs versions JS d'origine sont demandées. Pour ce faire, définissez une nouvelle route dans server.js avant que les fichiers ne soient diffusés avec 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 permet d'indiquer au serveur comment répondre à une requête GET pour un point de terminaison spécifique. Une fonction de rappel est ensuite utilisée pour définir comment gérer cette requête. L'itinéraire fonctionne de la manière suivante:

  • Si vous spécifiez '*.js' comme premier argument, cela signifie que cela fonctionne pour chaque point de terminaison déclenché pour récupérer un fichier JS.
  • Dans le rappel, .br est associé à l'URL de la requête et l'en-tête de réponse Content-Encoding est défini sur br.
  • L'en-tête Content-Type est défini sur application/javascript; charset=UTF-8 pour spécifier le type MIME.
  • Enfin, next() garantit que la séquence continue à tout rappel éventuellement suivant.

Étant donné que certains navigateurs peuvent ne pas être compatibles avec la compression Brotli, vérifiez que l'en-tête de requête Accept-Encoding inclut br avant de renvoyer le fichier compressé par brotli:

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

Une fois l'application actualisée, consultez à nouveau le panneau "Network".

Taille du bundle : 53,1 Ko (à partir de 225 Ko)

Opération réussie. Vous avez utilisé la compression Brotli pour compresser davantage vos éléments.

Conclusion

Cet atelier de programmation a montré comment brotli peut réduire davantage la taille globale de votre application. Lorsqu'il est pris en charge, brotli est un algorithme de compression plus puissant que gzip.