Netzwerknutzlasten mit Brotli reduzieren und komprimieren

Michael DiBlasio
Michael DiBlasio

Dieses Codelab ist eine Erweiterung des Codelabs „Netzwerknutzlasten minimieren und komprimieren“ und setzt voraus, dass Sie mit den grundlegenden Konzepten der Komprimierung vertraut sind. Im Vergleich zu anderen Komprimierungsalgorithmen wie gzip wird in diesem Codelab untersucht, wie die Brotli-Komprimierung (br) die Komprimierungsverhältnisse und die Gesamtgröße Ihrer App weiter reduzieren kann.

App – Screenshot

Messen

Bevor Sie Optimierungen vornehmen, sollten Sie zuerst den aktuellen Status der Anwendung analysieren.

  1. Klicken Sie auf Remix erstellen, um zu bearbeiten, um das Projekt bearbeitbar zu machen.
  2. Wenn Sie sich eine Vorschau der Website ansehen möchten, klicken Sie auf View App (App ansehen) und dann auf Fullscreen (Vollbild) Vollbild.

Im vorherigen Codelab „Netzwerknutzlasten minimieren und komprimieren“ haben wir die Größe von main.js von 225 KB auf 61,6 KB reduziert. In diesem Codelab erfahren Sie, wie Sie die Bundle-Größe mit der Brotli-Komprimierung noch weiter reduzieren können.

Brotli-Komprimierung

Brotli ist ein neuerer Komprimierungsalgorithmus, der noch bessere Ergebnisse bei der Textkomprimierung als gzip liefern kann. Laut CertSimple ist die Brotli-Leistung:

  • 14 % kleiner als gzip für JavaScript
  • 21 % kleiner als gzip für HTML
  • 17 % kleiner als gzip für CSS

Damit Sie Brotli verwenden können, muss Ihr Server HTTPS unterstützen. Brotli wird in allen modernen Browsern unterstützt. Browser, die Brotli unterstützen, enthalten br in Accept-Encoding-Headern:

Accept-Encoding: gzip, deflate, br

Sie können feststellen, welcher Komprimierungsalgorithmus verwendet wird, indem Sie das Feld Content-Encoding auf dem Tab „Netzwerk“ der Chrome-Entwicklertools (Command+Option+I oder Ctrl+Alt+I) prüfen:

Netzwerkbereich. In der Spalte „Content-Encoding“ werden die Codierungen angezeigt, die für verschiedene Assets verwendet werden, einschließlich gzip und brotli (br).

Brotli aktivieren

Wie Sie einen Webserver für das Senden von Brotli-codierten Ressourcen einrichten, hängt davon ab, wie Sie sie codieren möchten. Sie haben die Möglichkeit, Ressourcen zum Zeitpunkt der Anfrage dynamisch mit Brotli zu komprimieren (dynamisch) oder sie im Voraus zu codieren, sodass sie bereits komprimiert sind, wenn der Nutzer sie anfordert (statisch).

Dynamische Komprimierung

Bei der dynamischen Komprimierung werden Assets on the fly komprimiert, wenn sie vom Browser angefordert werden.

Vorteile

  • Gespeicherte komprimierte Versionen von Assets müssen nicht erstellt und aktualisiert werden.
  • Die On-the-fly-Komprimierung eignet sich besonders gut für dynamisch generierte Webseiten.

Nachteile

  • Das Komprimieren von Dateien auf höheren Stufen, um bessere Komprimierungsraten zu erzielen, dauert länger. Das kann zu Leistungseinbußen führen, da der Nutzer warten muss, bis die Assets komprimiert sind, bevor sie vom Server gesendet werden.

Dynamische Komprimierung mit Node und Express

Die Datei server.js ist für die Einrichtung des Knotenservers verantwortlich, auf dem die Anwendung gehostet wird.

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

Dabei wird lediglich express importiert und die Middleware express.static verwendet, um alle statischen HTML-, JS- und CSS-Dateien in public/directory zu laden. Diese Dateien werden von Webpack bei jedem Build erstellt.

Damit alle Assets bei jeder Anfrage mit Brotli komprimiert werden, können Sie das Modul shrink-ray verwenden. Fügen Sie sie zuerst als devDependency in package.json hinzu:

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

Importieren Sie sie in die Serverdatei server.js:

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

Fügen Sie es als Middleware hinzu, bevor express.static bereitgestellt wird:

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

// Compress all requests
app.use(shrinkRay());
app.use(express.static('public'));

Aktualisieren Sie die App und sehen Sie sich die Bundle-Größe im Netzwerkbereich an:

Bundle-Größe mit dynamischer Brotli-Komprimierung.

Sie können jetzt sehen, dass brotli von bz im Header Content-Encoding angewendet wird. main.bundle.js wird von 225 KB auf 53,1 KB reduziert. Das ist etwa 14 % kleiner als gzip (61,6 KB).

Statische Komprimierung

Die Idee hinter der statischen Komprimierung ist, dass Assets im Voraus komprimiert und gespeichert werden.

Vorteile

  • Latenz aufgrund hoher Komprimierungsstufen ist kein Problem mehr. Dateien müssen nicht mehr on the fly komprimiert werden, da sie jetzt direkt abgerufen werden können.

Nachteile

  • Assets müssen bei jedem Build komprimiert werden. Die Build-Zeiten können sich erheblich verlängern, wenn hohe Komprimierungsstufen verwendet werden.

Statische Komprimierung mit Node und Express mit webpack

Da bei der statischen Komprimierung Dateien im Voraus komprimiert werden, können die webpack-Einstellungen so geändert werden, dass Assets im Rahmen des Build-Schritts komprimiert werden. Dazu kann brotli-webpack-plugin verwendet werden.

Fügen Sie sie zuerst als devDependency in package.json hinzu:

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

Importieren Sie es wie jedes andere Webpack-Plug-in in die Konfigurationsdatei webpack.config.js:

var path = require("path");

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

und fügen Sie es dem Array „plugins“ hinzu:

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

Das Plug-in-Array verwendet die folgenden Argumente:

  • asset: Der Name des Ziel-Assets.
  • [file] wird durch den ursprünglichen Asset-Dateinamen ersetzt.
  • test: Alle Assets, die diesem regulären Ausdruck entsprechen (d. h. JavaScript-Assets, die auf .js enden), werden verarbeitet.

Beispiel: main.js würde in main.js.br umbenannt werden.

Wenn die App neu geladen und erstellt wird, wird jetzt eine komprimierte Version des Haupt-Bundles erstellt. Öffnen Sie die Glitch-Konsole, um sich den Inhalt des endgültigen Verzeichnisses public/ anzusehen, das vom Node-Server bereitgestellt wird.

  1. Klicken Sie auf den Button Tools.
  2. Klicken Sie auf den Button Console.
  3. Führen Sie in der Console die folgenden Befehle aus, um in das Verzeichnis public zu wechseln und alle Dateien darin aufzurufen:
cd public
ls -lh
Bundle-Größe mit statischer Brotli-Komprimierung

Die mit Brotli komprimierte Version des Bundles, main.bundle.js.br, wird jetzt ebenfalls hier gespeichert und ist etwa 76 % kleiner (225 KB im Vergleich zu 53 KB) als main.bundle.js.

Als Nächstes weisen Sie den Server an, diese mit Brotli komprimierten Dateien zu senden, wenn die ursprünglichen JS-Versionen angefordert werden. Dazu definieren Sie eine neue Route in server.js, bevor die Dateien mit express.static bereitgestellt werden.

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 wird verwendet, um dem Server mitzuteilen, wie er auf eine GET-Anfrage für einen bestimmten Endpunkt reagieren soll. Anschließend wird mit einer Callback-Funktion definiert, wie diese Anfrage verarbeitet werden soll. Die Route funktioniert so:

  • Wenn Sie '*.js' als erstes Argument angeben, funktioniert dies für jeden Endpunkt, der zum Abrufen einer JS-Datei ausgelöst wird.
  • Im Callback wird .br an die URL der Anfrage angehängt und der Antwortheader Content-Encoding wird auf br gesetzt.
  • Der Header Content-Type ist auf application/javascript; charset=UTF-8 festgelegt, um den MIME-Typ anzugeben.
  • Schließlich sorgt next() dafür, dass die Sequenz mit dem nächsten Callback fortgesetzt wird.

Da einige Browser die Brotli-Komprimierung möglicherweise nicht unterstützen, sollten Sie prüfen, ob Brotli unterstützt wird, bevor Sie die mit Brotli komprimierte Datei zurückgeben. Prüfen Sie dazu, ob der Anfrageheader Accept-Encoding den Wert br enthält:

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

Sobald die App neu geladen wurde, sehen Sie sich den Netzwerkbereich noch einmal an.

Bundle-Größe von 53,1 KB (von 225 KB)

Fertig! Sie haben die Brotli-Komprimierung verwendet, um Ihre Assets weiter zu komprimieren.

Fazit

In diesem Codelab wurde gezeigt, wie Sie mit brotli die Gesamtgröße Ihrer App weiter reduzieren können. Wo unterstützt, ist brotli ein leistungsstärkerer Komprimierungsalgorithmus als gzip.