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 tym Codelab porównujemy algorytmy kompresji, np. gzip, i sprawdzamy, jak kompresja Brotli (br) może jeszcze bardziej zmniejszyć współczynniki kompresji i ogólny rozmiar aplikacji.

Zrzut ekranu aplikacji

Zmierz odległość

Zanim zaczniesz wprowadzać optymalizacje, dobrze jest najpierw przeanalizować obecny stan aplikacji.

  1. Kliknij Remix to Edit (Zmiksuj do edycji), aby umożliwić edycję projektu.
  2. Aby wyświetlić podgląd strony, kliknij Wyświetl aplikację. Następnie kliknij Pełny ekranpeł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. W tym laboratorium programistycznym dowiesz się, jak kompresja Brotli może jeszcze bardziej zmniejszyć rozmiar pakietu.

Kompresja Brotli

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

  • 14% mniejsze niż gzip w przypadku JavaScript
  • 21% mniejsze niż gzip w przypadku kodu HTML
  • 17% mniejsze niż gzip w przypadku kodu CSS

Aby można było używać wersji Brotli, Twój serwer musi obsługiwać protokół HTTPS. Brotli jest obsługiwany we wszystkich nowoczesnych przeglądarkach. Przeglądarki, które obsługują Brotli, będą zawierać br w nagłówkach Accept-Encoding:

Accept-Encoding: gzip, deflate, br

Który algorytm kompresji jest używany, możesz sprawdzić na karcie Network (Sieć) w Narzędziach deweloperskich w Chrome (Content-Encoding lub Ctrl+Alt+I):

Panel Sieć. Kolumna Kodowanie treści zawiera kodowania używane w różnych zasobach, w tym gzip i brotli (br).

Jak włączyć Brotli

Sposób konfiguracji serwera WWW do wysyłania zasobów zakodowanych w formacie Brotli zależy od tego, jak planujesz je zakodować. Możesz dynamicznie kompresować zasoby za pomocą Brotli w momencie wysyłania żądania (dynamicznie) lub zakodować je z wyprzedzeniem, aby były już skompresowane w momencie, gdy użytkownik je zażąda (statycznie).

Kompresja dynamiczna

Kompresja dynamiczna polega na kompresowaniu zasobów na bieżąco, gdy są one żądane przez przeglądarkę.

Zalety

  • Nie musisz tworzyć ani aktualizować zapisanych, skompresowanych wersji zasobów.
  • Kompresowanie na bieżąco sprawdza się zwłaszcza 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 musi czekać na skompresowanie zasobów, zanim zostaną wysłane przez serwer.

Kompresja dynamiczna za pomocą Node i Express

Plik server.js odpowiada za konfigurowanie serwera Node, na którym działa aplikacja.

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

Wszystko to polega na importowaniu express i używaniu pośrednika express.static do wczytywania wszystkich statycznych plików HTML, JS i CSS w public/directory (te pliki są tworzone przez webpack przy każdym tworzeniu).

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. Zacznij od dodania go jako devDependency w sekcji package.json:

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

I zaimportuj go do pliku serwera, server.js:

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

Dodaj go jako element pośredniczący przed zamontowaniem express.static:

// ...
const 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 kompresją Brotli.

W nagłówku Content-Encoding możesz teraz zobaczyć, że brotli jest stosowany z bz. Plik main.bundle.js został spakowany z 225 KB do 53,1 KB. Jest to o około 14% mniejszy rozmiar niż w przypadku gzip (61,6 KB).

Kompresja statyczna

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

Zalety

  • Opóźnienia spowodowane wysokim poziomem kompresji nie stanowią już problemu. Aby skompresować pliki, nie trzeba nic robić w locie, ponieważ można je pobrać bezpośrednio.

Wady

  • Zasoby muszą być kompresowane w ramach każdej kompilacji. Czas kompilacji może się znacznie wydłużyć, jeśli używasz wysokiego poziomu kompresji.

Statyczna kompresja za pomocą Node i Express z webpack

Kompresja statyczna polega na wcześniejszym skompresowaniu plików, więc ustawienia webpacka można zmodyfikować, aby kompresować zasoby w ramach etapu kompilacji. Do tego celu możesz użyć funkcji brotli-webpack-plugin.

Zacznij od dodania go jako devDependency w sekcji package.json:

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

Podobnie jak w przypadku innych wtyczek webpacka, 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 wtyczki używa tych argumentów:

  • asset: nazwa zasobu docelowego.
  • [file] zostanie zastąpiony pierwotną nazwą pliku zasobu.
  • test: przetwarzane są wszystkie zasoby pasujące do tego wyrażenia regularnego (czyli zasoby JavaScript kończące się na .js).

Na przykład identyfikator main.js zostałby zmieniony na main.js.br.

Przy ponownym ładowaniu aplikacji tworzona jest skompresowana wersja pakietu głównego. Otwórz konsolę Glitch, aby sprawdzić, co znajduje się w plikupublic/, który jest obsługiwany przez serwer Node.

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

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

Następnie powiedz serwerowi, aby wysyłał te pliki skompresowane za pomocą Brotli, gdy tylko pojawi się żądanie ich oryginalnych wersji. Aby to zrobić, zdefiniuj nową trasę w server.js, zanim pliki zostaną przesłane za pomocą express.static.

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 służy do informowania serwera, jak ma reagować na żądanie GET dotyczące konkretnego punktu końcowego. Następnie używa się funkcji wywołania zwrotnego, aby określić sposób obsługi tego żądania. Trasa działa w ten sposób:

  • Podanie wartości '*.js' jako pierwszego argumentu oznacza, że ta funkcja działa w przypadku każdego punktu końcowego, który jest wywoływany w celu pobrania pliku JS.
  • W wywołaniu zwrotnym parametr .br jest dołączany do adresu URL żądania, a nagłówek odpowiedzi Content-Encoding jest ustawiony na br.
  • Aby określić typ MIME, nagłówek Content-Type ma wartość application/javascript; charset=UTF-8.
  • Na koniec next() zapewnia, że sekwencja będzie kontynuowana w przypadku każdego wywołania zwrotnego, które może nastąpić.

Niektóre przeglądarki mogą nie obsługiwać kompresji brotli, dlatego przed zwróceniem skompresowanego pliku brotli sprawdź, czy przeglądarka obsługuje brotli. Aby to zrobić, sprawdź, czy nagłówek Accept-Encoding zawiera br:

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

Gdy aplikacja zostanie ponownie załadowana, jeszcze raz sprawdź panel Sieć.

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

Gotowe! Użyłeś kompresji Brotli, aby jeszcze bardziej skompresować zasoby.

Podsumowanie

Ten warsztat programistyczny pokazuje, jak brotli może jeszcze bardziej zmniejszyć rozmiar aplikacji. W przypadku obsługi brotli jest to wydajniejszy algorytm kompresji niż gzip.