Minifikuj i kompresuj ładunki sieciowe za pomocą brotli

Michael DiBlasio
Michael DiBlasio

Te warsztaty to rozszerzenie warsztatów na temat minimalizowania i kompresowania ładunków sieciowych. Zakładamy, że znasz podstawowe pojęcia związane z kompresją. W porównaniu z innymi algorytmami kompresji, takimi jak gzip, w tym laboratorium dowiesz się, jak kompresja Brotli (br) może jeszcze bardziej zmniejszyć współczynniki kompresji i ogólny rozmiar aplikacji.

Zrzut ekranu aplikacji

Pomiary

Zanim zaczniesz dodawać optymalizacje, warto najpierw przeanalizować obecny stan aplikacji.

  1. Kliknij Remiksuj, aby edytować, aby umożliwić edycję projektu.
  2. Aby wyświetlić podgląd strony, kliknij Wyświetl aplikację, a następnie Pełny ekran pełny ekran.

W poprzednim samouczku dotyczącym minifikacji i kompresji ładunków sieciowych zmniejszyliśmy rozmiar pliku main.js z 225 KB do 61,6 KB. W tym laboratorium kodowania dowiesz się, jak kompresja Brotli może jeszcze bardziej zmniejszyć rozmiar tego pakietu.

Kompresja Brotli

Brotli to nowszy algorytm kompresji, który może zapewniać jeszcze lepsze wyniki kompresji tekstu niż gzip. Według CertSimple wydajność Brotli jest następująca:

  • o 14% mniejszy niż gzip w przypadku JavaScriptu.
  • 21% mniejszy niż gzip w przypadku HTML
  • o 17% mniejszy niż gzip w przypadku CSS

Aby używać Brotli, serwer musi obsługiwać HTTPS. Brotli jest obsługiwany we wszystkich nowoczesnych przeglądarkach. Przeglądarki obsługujące Brotli będą zawierać br w nagłówkach Accept-Encoding:

Accept-Encoding: gzip, deflate, br

Aby sprawdzić, który algorytm kompresji jest używany, skorzystaj z pola Content-Encoding na karcie Sieć w Narzędziach deweloperskich w Chrome (Command+Option+I lub Ctrl+Alt+I):

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

Jak włączyć Brotli

Sposób konfiguracji serwera internetowego do wysyłania zasobów zakodowanych w Brotli zależy od tego, jak zamierzasz je kodować. Możesz dynamicznie kompresować zasoby za pomocą Brotli w momencie żądania (kompresja dynamiczna) lub zakodować je z wyprzedzeniem, aby były już skompresowane, gdy użytkownik o nie poprosi (kompresja statyczna).

Kompresja dynamiczna

Kompresja dynamiczna polega na kompresowaniu zasobów na bieżąco, gdy przeglądarka wysyła żądanie ich pobrania.

Zalety

  • Nie trzeba tworzyć ani aktualizować zapisanych skompresowanych wersji komponentów.
  • Kompresja w czasie rzeczywistym sprawdza się szczególnie w przypadku stron internetowych generowanych dynamicznie.

Wady

  • Kompresowanie plików na wyższych poziomach w celu uzyskania lepszych współczynników kompresji trwa dłużej. Może to negatywnie wpłynąć na wydajność, ponieważ użytkownik musi poczekać, aż zasoby zostaną skompresowane, zanim serwer je wyśle.

Kompresja dynamiczna za pomocą Node i Express

Plik server.js odpowiada za skonfigurowanie serwera Node, który hostuje aplikację.

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, co robi ten kod, to importowanie express i używanie express.static oprogramowania pośredniczącego do wczytywania wszystkich statycznych plików HTML, JS i CSS w public/directory (pliki te są tworzone przez webpack przy każdej kompilacji).

Aby mieć pewność, że wszystkie zasoby są kompresowane za pomocą brotli za każdym razem, gdy są o nie wysyłane żądania, można użyć modułu shrink-ray. Zacznij od dodania go jako devDependency w package.json:

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

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 elementu express.static:

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

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

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

Rozmiar pakietu z dynamiczną kompresją Brotli.

W nagłówku Content-Encoding widać teraz, że od bz zastosowano brotli. main.bundle.js zmniejszył się z 225 KB do 53,1 KB. Jest to o ok.14% mniej niż w przypadku gzip (61,6 KB).

Kompresja statyczna

Ideą kompresji statycznej jest kompresowanie i zapisywanie zasobów z wyprzedzeniem.

Zalety

  • Opóźnienia spowodowane wysokim poziomem kompresji nie stanowią już problemu. Nie trzeba kompresować plików na bieżąco, ponieważ można je teraz pobierać bezpośrednio.

Wady

  • Zasoby muszą być kompresowane przy każdej kompilacji. Czas kompilacji może się znacznie wydłużyć, jeśli używane są wysokie poziomy kompresji.

Statyczna kompresja za pomocą Node.js i Express z webpackiem

Statyczna kompresja polega na wcześniejszym skompresowaniu plików, więc ustawienia webpacka 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"
},

Podobnie jak w przypadku innych wtyczek webpacka, zaimportuj ją w pliku konfiguracji:webpack.config.js

var path = require("path");

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

i dodaj go do tablicy wtyczek:

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

Tablica wtyczek używa tych argumentów:

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

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

Gdy aplikacja zostanie ponownie załadowana i przebudowana, zostanie utworzona skompresowana wersja głównego pakietu. Otwórz konsolę Glitch, aby zobaczyć, co znajduje się w katalogu final public/, 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 za pomocą algorytmu Brotli, main.bundle.js.br, jest teraz zapisywana również tutaj i jest o ok. 76% mniejsza (225 KB w porównaniu z 53 KB) niż main.bundle.js.

Następnie poinformuj serwer, aby wysyłał te skompresowane pliki Brotli, gdy tylko będą żądane ich oryginalne wersje JS. Możesz to zrobić, definiując nową ścieżkę w server.js, zanim pliki zostaną udostępnione 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 odpowiadać na żądanie GET dotyczące konkretnego punktu końcowego. Funkcja wywołania zwrotnego służy następnie do określania sposobu obsługi tego żądania. Trasa wygląda tak:

  • Określenie '*.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 ustawiany na wartość br.
  • Nagłówek Content-Type jest ustawiony na application/javascript; charset=UTF-8, aby określić typ MIME.
  • Na koniec next() zapewnia kontynuację sekwencji do dowolnego wywołania zwrotnego, które może nastąpić później.

Niektóre przeglądarki mogą nie obsługiwać kompresji Brotli, dlatego przed zwróceniem skompresowanego pliku Brotli sprawdź, czy jest ona obsługiwana. W tym celu sprawdź, czy nagłówek żądania 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 (z 225 KB)

Gotowe! Używasz kompresji Brotli, aby jeszcze bardziej skompresować komponenty.

Podsumowanie

W tym laboratorium kodowania pokazaliśmy, jak brotli może jeszcze bardziej zmniejszyć ogólny rozmiar aplikacji. W obsługiwanych przypadkach brotli jest bardziej wydajnym algorytmem kompresji niż gzip.