Minifikuj i kompresuj ładunki sieciowe za pomocą brotli

Michael DiBlasio
Michael DiBlasio

To ćwiczenie w Codelabs jest rozszerzeniem minifikowania 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, w ramach tego ćwiczenia w Codelabs dowiesz się, jak kompresja Brutli może jeszcze bardziej zmniejszyć współczynniki kompresji oraz ogólny rozmiar Twojej aplikacji.

Zrzut ekranu aplikacji

Zmierz odległość

Zanim zagłębimy się w temat optymalizacji, warto najpierw przeanalizować bieżący stan aplikacji.

  1. Aby udostępnić projekt do edycji, kliknij Remiksuj, aby edytować.
  2. Aby wyświetlić podgląd witryny, kliknij Wyświetl aplikację, a następnie naciśnij Pełny ekran pełny ekran.

W poprzednim ćwiczeniu z programowania dotyczącym minifikowania i kompresowania ładunków sieciowych zmniejszyliśmy rozmiar main.js z 225 KB do 61,6 KB. Z tego ćwiczenia w Codelabs dowiesz się, jak kompresja Brotli może jeszcze bardziej zmniejszyć ten rozmiar pakietu.

Kompresja Brotli

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

  • O 14% mniejszy niż gzip w przypadku JavaScriptu
  • O 21% mniejsza niż gzip w przypadku kodu HTML
  • O 17% mniejsza niż gzip w przypadku usługi porównywania cen

Aby można było używać wersji Brotli, Twój serwer musi obsługiwać protokół HTTPS. Reklamy typu Brotli są obsługiwane w najnowszych wersjach większości przeglądarek. Przeglądarki obsługujące przeglądarkę Brotli będą umieszczać w nagłówkach Accept-Encoding ciąg br:

Accept-Encoding: gzip, deflate, br

Używany algorytm kompresji możesz sprawdzić w polu Content-Encoding na karcie Sieć w Narzędziach deweloperskich w Chrome (Command+Option+I lub Ctrl+Alt+I):

Panel sieci

Włączam Brotli

Kompresja dynamiczna

Kompresja dynamiczna polega na kompresowaniu zasobów na bieżąco w odpowiedzi na żądanie przeglądarki.

Zalety

  • Nie musisz tworzyć ani aktualizować zapisanych, skompresowanych wersji zasobów.
  • Kompresja „w locie” 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ć trafienie na wydajność, gdy użytkownik czeka na skompresowanie zasobów przed ich wysłaniem przez serwer.

Dynamiczna kompresja Node/Express

Plik server.js odpowiada za skonfigurowanie serwera węzła, 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ć plik express i użyć oprogramowania pośredniczącego express.static, aby wczytać wszystkie statyczne pliki HTML, JS i CSS w public/directory (a pliki te są tworzone w pakiecie internetowym przy każdej kompilacji).

Aby mieć pewność, że wszystkie zasoby są skompresowane za pomocą narzędzia brotli za każdym razem, gdy są one wysyłane, można użyć modułu shrink-ray. Najpierw dodaj go jako devDependency w aplikacji 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');

Przed podłączeniem usługi express.static dodaj ją jako oprogramowanie pośredniczące:

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

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

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

Teraz załaduj ponownie aplikację i sprawdź rozmiar pakietu w panelu Sieć:

Rozmiar pakietu z dynamiczną kompresją Brotli

Teraz w nagłówku Content-Encoding widać, że atrybut brotli został zastosowany z poziomu bz. Rozmiar pliku main.bundle.js został zmniejszony z 225 KB do 53,1 KB. To o około 14% mniej w porównaniu z plikiem gzip (61,6 KB).

Kompresja statyczna

Idea kompresji statycznej polega na skompresowaniu i zapisaniu zasobów z wyprzedzeniem.

Zalety

  • Czas oczekiwania związany z wysokim poziomem kompresji nie jest już problemem. Teraz nie trzeba nic robić, aby kompresować pliki na bieżąco, ponieważ teraz można je pobierać bezpośrednio.

Wady

  • Zasoby muszą być skompresowane przy każdej kompilacji. Czas kompilacji może się znacznie wydłużyć w przypadku użycia wysokiego poziomu kompresji.

Kompresja statyczna z użyciem Node/Express i pakietu webpack

Kompresja statyczna obejmuje kompresowanie plików z wyprzedzeniem, dlatego ustawienia pakietu internetowego można zmienić w taki sposób, aby skompresować zasoby na etapie kompilacji. Można do tego używać obiektu brotli-webpack-plugin.

Najpierw dodaj go jako devDependency w aplikacji package.json:

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

Tak jak w przypadku każdej innej wtyczki pakietu internetowego, zaimportuj ją do pliku konfiguracji webpack.config.js:

var path = require("path");

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

Dodaj go do tablicy wtyczek:

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

Tablica wtyczek używa następujących argumentów:

  • asset: nazwa zasobu docelowego.
  • Pole [file] zostało zastąpione nazwą oryginalnego pliku zasobu.
  • test: wszystkie zasoby pasujące do tego wyrażenia regularnego (czyli zasoby JavaScript o numerze kończącym się cyframi .js) są przetwarzane.

Na przykład nazwa main.js zostanie zmieniona na main.js.br.

Przy ponownym ładowaniu aplikacji tworzona jest skompresowana wersja pakietu głównego. Otwórz konsolę Glitcha, aby zobaczyć, co znajduje się w ostatecznym katalogu public/ obsługiwanym przez serwer węzłów.

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

Tutaj również została zapisana skompresowana wersja brotli pakietu main.bundle.js.br, która jest około 76% mniejsza (225 KB zamiast 53 KB) niż main.bundle.js.

Następnie poleć serwerowi, aby wysyłał te pliki skompresowane brotli za każdym razem, gdy zostaną zażądane ich oryginalne wersje JS. W tym celu zdefiniuj 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 odpowiedzieć na żądanie GET dotyczące określonego punktu końcowego. Następnie za pomocą funkcji wywołania zwrotnego można określić sposób obsługi tego żądania. Trasa wygląda tak:

  • Określenie '*.js' jako pierwszego argumentu oznacza, że działa on w przypadku każdego punktu końcowego, który jest wywoływany w celu pobrania pliku JS.
  • W wywołaniu zwrotnym do adresu URL żądania jest dołączony tag .br, a nagłówek odpowiedzi Content-Encoding ma wartość br.
  • Aby określić typ MIME, nagłówek Content-Type ma wartość application/javascript; charset=UTF-8.
  • next() zapewnia też, że sekwencja będzie kontynuowana przy każdym wywołaniu zwrotnym.

Niektóre przeglądarki mogą nie obsługiwać kompresji brotli, dlatego przed zwróceniem pliku brotli sprawdź, czy jest on obsługiwany. W tym celu sprawdź, czy nagłówek żądania Accept-Encoding zawiera ciąg 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 jeszcze raz przyjrzyj się panelowi Network (Sieć).

Rozmiar pakietu: 53,1 KB (z 225 KB)

Gotowe. Do dalszego skompresowania zasobów użyto kompresji Brotli.

Podsumowanie

To ćwiczenie w Codelabs pokazuje, jak brotli może jeszcze bardziej zmniejszyć ogólny rozmiar aplikacji. brotli jest zaawansowanym algorytmem kompresji niż gzip (o ile jest obsługiwany).