Minifikuj i kompresuj ładunki sieciowe za pomocą brotli

Michael DiBlasio
Michael DiBlasio

To ćwiczenie w Codelabs jest dodatkiem do minimalizowania i kompresowania ładunków sieciowych. Zakładamy w nim, że znasz podstawowe pojęcia związane z kompresją. W porównaniu z innymi algorytmami kompresji, takimi jak gzip, to ćwiczenie w Codelabs pokazuje, jak kompresja Britli może jeszcze bardziej zmniejszyć współczynnik kompresji i ogólny rozmiar aplikacji.

Zrzut ekranu aplikacji

Zmierz odległość

Przed zagłębieniem się w optymalizacje warto najpierw przeanalizować bieżący stan aplikacji.

  1. Aby umożliwić edytowanie projektu, kliknij Zremiksuj do edycji.
  2. Aby wyświetlić podgląd strony, kliknij Wyświetl aplikację, a potem Pełny ekran pełny ekran.

W poprzednim ćwiczeniach z programowania: minifikowanie i kompresowanie ładunków sieciowych zmniejszyliśmy rozmiar main.js z 225 KB do 61,6 KB. W ramach tego ćwiczenia w programie zobaczysz, jak kompresja Brotli może jeszcze bardziej zmniejszyć rozmiar pakietu.

Kompresja Brotli

Brotli to nowszy algorytm kompresji, który zapewnia jeszcze lepsze wyniki kompresji tekstu niż gzip. Według CertSimple skuteczność Brotli:

  • O 14% mniejsza niż w przypadku języka gzip w przypadku JavaScriptu
  • O 21% mniejszy niż gzip w przypadku HTML
  • O 17% mniejsza niż w przypadku usługi porównywania cen (gzip)

Aby można było korzystać z brotli, Twój serwer musi obsługiwać protokół HTTPS. Brotli działa w najnowszych wersjach większości przeglądarek. Przeglądarki, które obsługują Brotli, umieszczają nagłówek br w nagłówkach Accept-Encoding:

Accept-Encoding: gzip, deflate, br

Używany algorytm kompresji możesz określić w polu Content-Encoding na karcie Sieć Narzędzi dla deweloperów w Chrome (Command+Option+I lub Ctrl+Alt+I):

Panel sieci

Włączanie Brotli

Kompresja dynamiczna

Kompresja dynamiczna obejmuje kompresowanie zasobów w czasie rzeczywistym, gdy przeglądarka wysyła ich żądania.

Zalety

  • Nie musisz tworzyć i aktualizować zapisanych skompresowanych wersji zasobów.
  • Kompresja „w czasie rzeczywistym” sprawdza się szczególnie dobrze w przypadku stron internetowych generowanych dynamicznie.

Wady

  • Kompresja plików na wyższych poziomach w celu uzyskania lepszych współczynników kompresji trwa dłużej. Może to spowodować spadek wydajności, ponieważ użytkownik czeka na skompresowanie zasobów, zanim zostaną one przesłane przez serwer.

Dynamiczna kompresja z użyciem węzła/Express

Plik server.js odpowiada za skonfigurowanie serwera węzłów, na którym jest hostowana aplikacja.

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

Obecnie wystarczy zaimportować express i użyć oprogramowania pośredniczącego express.static, aby wczytać wszystkie statyczne pliki HTML, JS i CSS w komponencie public/directory (pliki te są tworzone przez pakiet internetowy przy każdej kompilacji).

Aby mieć pewność, że wszystkie zasoby są skompresowane za pomocą narzędzia brotli za każdym razem, gdy o ich zażądamy, możesz użyć modułu shrink-ray. Zacznij od dodania go jako devDependency w package.json:

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

I zaimportuj go do pliku serwera server.js:

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

I dodaj je jako oprogramowanie pośredniczące przed podłączeniem express.static:

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

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

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

Ponownie załaduj aplikację i spójrz na rozmiar pakietu w panelu Sieć:

Rozmiar pakietu z dynamiczną kompresją Brotli

W nagłówku Content-Encoding możesz teraz zobaczyć, jak zastosowano brotli z adresu bz. Plik main.bundle.js został zmniejszony z 225 KB do 53,1 KB! Jest to o około 14% mniej niż w przypadku gzip (61,6 KB).

Kompresja statyczna

Kompresja statyczna ma na celu skompresowanie i zapisanie zasobów z wyprzedzeniem.

Zalety

  • Opóźnienie spowodowane wysokim poziomem kompresji nie jest już problemem. Kompresowanie plików nie musi odbywać się na bieżąco, ponieważ teraz można je pobierać bezpośrednio.

Wady

  • Przy każdej kompilacji zasoby muszą być skompresowane. Czas kompilacji może się znacznie wydłużyć, jeśli stosowane są wysokie poziomy kompresji.

Kompresja statyczna z użyciem węzła/Express i pakietu webpack

Kompresja statyczna obejmuje kompresowanie plików z wyprzedzeniem, dlatego ustawienia pakietu internetowego można zmodyfikować tak, aby kompresować zasoby w ramach etapu kompilacji. Do tego celu można użyć brotli-webpack-plugin.

Zacznij od dodania go jako devDependency w package.json:

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

Jak każdą inną wtyczkę pakietu internetowego, zaimportuj ją do pliku konfiguracji webpack.config.js:

var path = require("path");

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

Uwzględnij go w tablicy wtyczek:

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

Tablica wtyczek używa tych argumentów:

  • asset: nazwa zasobu docelowego.
  • Wartość [file] zostanie zastąpiona oryginalną nazwą pliku zasobu.
  • test: wszystkie zasoby, które pasują do tego wyrażenia regularnego (czyli zasoby JavaScript kończące się na .js), są przetwarzane.

Na przykład nazwa main.js zostałaby zmieniona na main.js.br.

Gdy aplikacja załaduje się ponownie i ponownie skompiluje, tworzona jest skompresowana wersja pakietu głównego. Otwórz konsolę Glitch, aby zobaczyć, co znajduje się w końcowym katalogu public/ obsługiwanym przez serwer węzłów.

  1. Kliknij przycisk Narzędzia.
  2. Kliknij przycisk Konsola.
  3. W konsoli uruchom te polecenia, aby przejść do katalogu public i wyświetlić wszystkie znajdujące się w nim pliki:
cd public
ls -lh
Rozmiar pakietu ze statyczną kompresją Brotli

Skompresowana wersja pakietu brotli, main.bundle.js.br, również jest teraz zapisywana tutaj. Jest ona o około 76% mniejsza (225 KB w porównaniu z 53 KB) niż main.bundle.js.

Następnie poproś serwer, aby wysyłał te pliki skompresowane w postaci brotli za każdym razem, gdy wymagane jest ich oryginalne wersje JS. Możesz to zrobić, definiując nową trasę w server.js, zanim pliki zostaną udostępnione za pomocą 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 informuje serwer, jak ma odpowiedzieć na żądanie GET dotyczące określonego punktu końcowego. Za pomocą funkcji wywołania zwrotnego można następnie określić sposób obsługi tego żądania. Trasa działa w następujący sposób:

  • Jeśli jako pierwszy argument określisz '*.js', będzie to działać w przypadku każdego punktu końcowego, który uruchamia się w celu pobrania pliku JS.
  • W wywołaniu zwrotnym adres .br jest dołączony do adresu URL żądania, a nagłówek odpowiedzi Content-Encoding jest ustawiony na br.
  • Nagłówek Content-Type jest ustawiony na application/javascript; charset=UTF-8 w celu określenia typu MIME.
  • next() dba też o to, aby sekwencja obejmowała kolejne wywołania zwrotne.

Niektóre przeglądarki mogą nie obsługiwać kompresji brotli, więc zanim zwrócisz plik skompresowany z brotli, sprawdź, czy jest ona obsługiwana. Aby to zrobić, sprawdź, czy nagłówek żądania Accept-Encoding zawiera parametr 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'));

Po ponownym załadowaniu aplikacji przyjrzyj się jeszcze raz panelowi Network (Sieć).

Rozmiar pakietu 53,1 KB (z 225 KB)

Success! Udało Ci się użyć kompresji Brotli, aby jeszcze bardziej skompresować swoje zasoby.

Podsumowanie

To ćwiczenie z programowania pokazuje, jak brotli może jeszcze bardziej zmniejszyć ogólny rozmiar aplikacji. Tam, gdzie jest obsługiwany, algorytm brotli jest bardziej zaawansowany niż gzip.