Minifikuj i kompresuj ładunki sieciowe za pomocą brotli

Michael DiBlasio
Michael DiBlasio

To ćwiczenie jest rozszerzeniem ćwiczenia z zakresu minifikacji i kompresji danych przesyłanych przez sieć i zakłada, że znasz podstawowe pojęcia związane z kompresją. W porównaniu z innymi algorytmami kompresji, takimi jak gzip, ten ćwiczenie pokazuje, 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 dodawać optymalizacje, warto najpierw przeanalizować bieżący stan aplikacji.

  1. Kliknij Zremiksuj, aby edytować, aby umożliwić edytowanie projektu.
  2. Aby wyświetlić podgląd witryny, naciśnij Wyświetl aplikację, a następnie Pełny ekran pełny ekran.

W poprzednim ćwiczeniu z minifikacji i kompresji ładunków sieciowych zmniejszyliśmy rozmiar pliku main.js z 225 KB do 61,6 KB. W tym ćwiczeniu 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 jest:

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

Aby używać Brotli, serwer musi obsługiwać protokół HTTPS. Algorytm 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

Algorytm kompresji możesz określić za pomocą pola Content-Encoding na karcie Sieć w Narzędziach deweloperskich w Chrome (Command+Option+I lub Ctrl+Alt+I):

Panel Sieć. W kolumnie Kodowanie zawartości wyświetlane są kodowania używane w przypadku różnych zasobów, w tym gzip i brotli (br).

Jak włączyć Brotli

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

Kompresja dynamiczna

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

Zalety

  • Nie trzeba tworzyć ani aktualizować zapisanych skompresowanych wersji zasobów.
  • Kompresja w locie sprawdza się szczególnie dobrze 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 spowodować spadek wydajności, ponieważ użytkownik musi czekać na skompresowanie zasobów, zanim zostaną wysłane przez serwer.

Kompresja dynamiczna z użyciem Node i Express

Plik server.js odpowiada za skonfigurowanie serwera Node, na którym jest hostowana 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, co robi, to importowanie express i używanie oprogramowania pośredniczącego express.static do wczytywania wszystkich statycznych plików HTML, JS i CSS w public/directory (te pliki są tworzone przez webpack przy każdej kompilacji).

Aby mieć pewność, że wszystkie zasoby są kompresowane za pomocą algorytmu Brotli przy każdym żądaniu, 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:

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

I dodaj go jako oprogramowanie pośredniczące przed zamontowaniem 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 możesz teraz zobaczyć, że brotli jest stosowany z bz. Rozmiar pliku main.bundle.js został zmniejszony z 225 KB do 53,1 KB. To o około 14% mniej niż w przypadku gzip (61,6 KB).

Kompresja statyczna

Idea kompresji statycznej polega na tym, że zasoby są kompresowane i zapisywane 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. Jeśli używane są wysokie poziomy kompresji, czas kompilacji może znacznie wzrosnąć.

Kompresja statyczna z Node i Express z webpackiem

Ponieważ kompresja statyczna polega na kompresowaniu plików z wyprzedzeniem, można zmodyfikować ustawienia webpacka, aby kompresować zasoby w ramach etapu kompilacji. Możesz do tego 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 każdej innej wtyczki webpack, zaimportuj ją w pliku konfiguracji webpack.config.js:

var path = require("path");

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

I 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.
  • [file] jest zastępowany nazwą pliku komponentu głównego.
  • test: przetwarzane są wszystkie zasoby pasujące do tego wyrażenia regularnego (czyli zasoby JavaScriptu kończące się na .js).

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

Gdy aplikacja zostanie ponownie załadowana i skompilowana, zostanie utworzona skompresowana wersja głównego pakietu. Otwórz konsolę Glitch, aby zobaczyć, co znajduje się w katalogu public/ obsługiwanym 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

Skompresowana za pomocą algorytmu Brotli wersja pakietu main.bundle.js.br jest teraz zapisana również tutaj i jest o około 76% mniejsza (225 KB w porównaniu z 53 KB) niż main.bundle.js.

Następnie poinstruuj serwer, aby wysyłał te pliki skompresowane za pomocą Brotli, gdy żądane są ich oryginalne wersje JS. Można to zrobić, definiując nową trasę w pliku 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. Następnie używana jest funkcja wywołania zwrotnego, która określa, jak obsłużyć to żądanie. Trasa działa w ten sposób:

  • Określenie '*.js' jako pierwszego argumentu oznacza, że działa to 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 br.
  • Nagłówek Content-Type jest ustawiony na application/javascript; charset=UTF-8, aby określić typ MIME.
  • Na koniec next() zapewnia, że sekwencja będzie kontynuowana do dowolnego wywołania zwrotnego, które może być następne.

Niektóre przeglądarki mogą nie obsługiwać kompresji brotli, dlatego przed zwróceniem pliku skompresowanego za pomocą 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 się załaduje, ponownie spójrz na panel Sieć.

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

Gotowe! Użyto kompresji Brotli, aby dodatkowo skompresować zasoby.

Podsumowanie

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