Netzwerknutzlasten mit Brotli reduzieren und komprimieren

Michael DiBlasio
Michael DiBlasio

Dieses Codelab ist eine Erweiterung des Codelabs zum Minifizieren und Komprimieren von Netzwerknutzlasten. Es wird davon ausgegangen, dass Sie mit den grundlegenden Komprimierungskonzepten vertraut sind. In diesem Codelab erfahren Sie, wie sich mit der Brotli-Komprimierung (br) im Vergleich zu anderen Komprimierungsalgorithmen wie gzip die Komprimierungsraten und die Gesamtgröße Ihrer App weiter reduzieren lassen.

App – Screenshot

Messen

Bevor Sie mit der Optimierung beginnen, sollten Sie den aktuellen Zustand der Anwendung analysieren.

  1. Klicke auf Remix zum Bearbeiten, um das Projekt bearbeitbar zu machen.
  2. Wenn Sie sich eine Vorschau der Website ansehen möchten, drücken Sie App ansehen und dann Vollbild Vollbild.

Im vorherigen Codelab zum Minimieren und Komprimieren von Netzwerknutzlasten haben wir die Größe von main.js von 225 KB auf 61,6 KB reduziert. In diesem Codelab erfahren Sie, wie Sie diese 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 Leistung von Brotli:

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

Damit Brotli verwendet werden kann, muss Ihr Server HTTPS unterstützen. Brotli wird in allen modernen Browsern unterstützt. Browser, die Brotli unterstützen, fügen br in Accept-Encoding-Header ein:

Accept-Encoding: gzip, deflate, br

Welcher Komprimierungsalgorithmus verwendet wird, können Sie im Feld Content-Encoding auf dem Tab „Netzwerk“ der Chrome-Entwicklertools (Command+Option+I oder Ctrl+Alt+I) ermitteln:

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 zum Senden von Brotli-codierten Ressourcen einrichten, hängt davon ab, wie Sie sie codieren möchten. Sie haben die Möglichkeit, Ressourcen bei der Anfrage dynamisch mit Brotli zu komprimieren (dynamisch) oder sie im Voraus zu codieren, damit sie bereits komprimiert sind, wenn der Nutzer sie anfordert (statisch).

Dynamische Komprimierung

Bei der dynamischen Komprimierung werden Assets direkt komprimiert, wenn sie vom Browser angefordert werden.

Vorteile

  • Es ist nicht erforderlich, gespeicherte komprimierte Versionen von Assets zu erstellen und zu aktualisieren.
  • Das On-the-fly-Komprimieren eignet sich besonders für Webseiten, die dynamisch generiert werden.

Nachteile

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

Dynamische Komprimierung mit Node und Express

Die Datei server.js ist für die Einrichtung des Node-Servers 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 nur express importiert und die express.static-Middleware verwendet, um alle statischen HTML-, JS- und CSS-Dateien in public/directory zu laden. Diese Dateien werden bei jedem Build von webpack erstellt.

Damit alle Assets bei jeder Anfrage mit Brotli komprimiert werden, kann das Modul shrink-ray verwendet werden. Fügen Sie es zuerst als devDependency in package.json hinzu:

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

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

Laden Sie die App jetzt neu und sehen Sie sich die Bundle-Größe im Bereich „Netzwerk“ an:

Größe des Bundles mit dynamischer Brotli-Komprimierung.

In der Kopfzeile von Content-Encoding sehen Sie jetzt, dass brotli von bz angewendet wird. main.bundle.js wurde von 225 KB auf 53,1 KB reduziert. Das ist etwa 14% kleiner als gzip (61,6 KB).

Statische Komprimierung

Bei der statischen Komprimierung werden Assets im Voraus komprimiert und gespeichert.

Vorteile

  • Latenzen aufgrund hoher Komprimierungsstufen sind 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 es 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');

Fügen Sie es in das „plugins“-Array ein:

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 Namen der Asset-Datei ersetzt.
  • test: Alle Assets, die mit diesem regulären Ausdruck übereinstimmen (d. h. JavaScript-Assets, die auf .js enden), werden verarbeitet.

Beispiel: main.js wird in main.js.br umbenannt.

Wenn die App neu geladen und neu erstellt wird, wird jetzt eine komprimierte Version des Haupt-Bundles erstellt. Öffnen Sie die Glitch Console, um sich anzusehen, was sich im endgültigen public/-Verzeichnis befindet, das vom Node-Server bereitgestellt wird.

  1. Klicken Sie auf die Schaltfläche Tools.
  2. Klicken Sie auf die Schaltfläche Console.
  3. Führen Sie in der Konsole die folgenden Befehle aus, um in das Verzeichnis public zu wechseln und alle darin enthaltenen Dateien 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 auch hier gespeichert. Sie ist etwa 76% kleiner (225 KB gegenüber 53 KB) als main.bundle.js.

Weisen Sie den Server als Nächstes 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 ausgeliefert 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'));

Mit app.get wird dem Server mitgeteilt, wie er auf eine GET-Anfrage für einen bestimmten Endpunkt reagieren soll. Mit einer Callback-Funktion wird dann festgelegt, wie diese Anfrage verarbeitet werden soll. So funktioniert die Route:

  • Wenn du '*.js' als erstes Argument angibst, funktioniert das 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 Content-Encoding-Antwortheader auf br gesetzt.
  • Der Header Content-Type ist auf application/javascript; charset=UTF-8 gesetzt, um den MIME-Typ anzugeben.
  • Schließlich sorgt next() dafür, dass die Sequenz mit dem nächsten möglichen Rückruf fortgesetzt wird.

Da einige Browser die Brotli-Komprimierung möglicherweise nicht unterstützen, solltest du vor dem Zurückgeben der mit Brotli komprimierten Datei prüfen, ob Brotli unterstützt wird. Dazu musst du prüfen, ob der Accept-Encoding-Anfrageheader 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'));

Sehen Sie sich nach dem Neuladen der App noch einmal das Netzwerkfeld an.

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

Fertig! Sie haben Ihre Assets mit der Brotli-Komprimierung weiter komprimiert.

Fazit

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