Opublikowano: 6 marca 2024 r.
Kompresja danych to sprawdzona technika optymalizacji wydajności, która zmniejsza rozmiar kwalifikujących się zasobów strony. Od pewnego czasu powszechną praktyką było używanie głównie gzip na serwerach WWW do kompresowania typowych zasobów strony opartych na tekście, takich jak pliki HTML, CSS i JavaScript, oraz wysyłanie ich do klienta, gdzie można je zdekompresować. Dzięki temu zasoby wczytują się szybciej, a strona działa zgodnie z oczekiwaniami.
Chociaż gzip jest bardzo skuteczny, w ostatnich latach wprowadzono dalsze ulepszenia w zakresie kompresji w internecie. W 2016 r. w Chrome pojawił się algorytm Brotli, który zapewnia ogólnie lepsze współczynniki kompresji w przypadku kwalifikujących się zasobów. Pod koniec 2017 r. wszystkie nowoczesne przeglądarki obsługiwały Brotli, a obsługa tego algorytmu na serwerach zaczęła się upowszechniać. Niedawno Chrome wprowadził kompresję ZStandard.
Ale to nie koniec! Zespół Chrome pracuje nad udostępnieniem w internecie słowników współdzielonych, które są teraz dostępne w ramach testów origin zarówno w przypadku Brotli, jak i ZStandard. Słowniki współdzielone mogą uzupełniać kompresję Brotli i ZStandard, aby zapewnić znacznie wyższe współczynniki kompresji w przypadku witryn, które często udostępniają zaktualizowany kod. W niektórych przypadkach mogą one zapewnić współczynniki kompresji na poziomie 90% lub wyższym. W tym poście znajdziesz więcej informacji o tym, jak działają słowniki współdzielone i jak zarejestrować się w testach origin, aby używać ich w swojej witrynie w przypadku Brotli i ZStandard. Możesz też obejrzeć ten film:
Wyjaśnienie działania słowników współdzielonych
Kompresja to proces wyszukiwania nadmiarowych sekwencji w danych wejściowych i wykorzystywania tych informacji do utworzenia znacznie mniejszych danych wyjściowych, które można później odwrócić. Kompresja dobrze sprawdza się w internecie, ponieważ znacznie skraca czas wczytywania zasobów. Zarówno Brotli, jak i ZStandard mogą zwiększyć swoją skuteczność dzięki użyciu słownika kompresji, czyli zbioru dodatkowych wzorców, które te algorytmy mogą wykorzystywać podczas kompresji. Wysoka skuteczność Brotli jest w pewnym stopniu osiągana dzięki użyciu słownika wewnętrznego.
Można jednak używać niestandardowych słowników tworzonych przez użytkowników, które zawierają wzorce specyficzne dla określonych zasobów. W praktyce słownik niestandardowy to plik zewnętrzny, który można zastosować do dowolnych danych wejściowych. Słowniki mogą być bardzo specyficzne dla kodu produkcyjnego aplikacji lub dowolnej innej treści. To, jak dobrze dany słownik pasuje do danych wejściowych, może mieć duży wpływ na ogólną skuteczność kompresji. Słowniki, które są bardzo podobne do zawartości danych wejściowych, będą generować dane wyjściowe o wyższych współczynnikach kompresji niż słowniki o ogólnej lub niepodobnej zawartości.
Oto przykład skuteczności niestandardowego słownika kompresji: załóżmy, że Twoja witryna korzysta z frameworka Angular, a używana przez Ciebie wersja to 1.7.9. Ta wersja frameworka Angular ma około 172 KiB bez kompresji. Po skompresowaniu za pomocą domyślnych ustawień Brotli jej rozmiar wynosi około 53 KiB. Daje to prawie 70% współczynnik kompresji. Załóżmy jednak, że później zdecydujesz się na aktualizację do Angulara 1.8.3. Ponieważ ta wersja Angulara ma mniej więcej taki sam rozmiar jak wersja 1.7.9, możesz oczekiwać prawie takiego samego współczynnika kompresji jak w poprzedniej wersji.
W tym przypadku przydatny może być słownik niestandardowy, który wykorzystuje proces znany jako kompresja różnicowa , czyli kompresowanie nowszej wersji za pomocą słownika z poprzedniej wersji zasobu. W poprzednim przykładzie, jeśli skompresujesz wersję 1.8.3 Angulara za pomocą wersji 1.7.9 jako słownika, dane wyjściowe będą miały nieco ponad 4 KiB. Daje to współczynnik kompresji wynoszący prawie 98%. Słowniki kompresji mogą mieć duży wpływ na wydajność wczytywania, a ich skuteczność została już potwierdzona w rzeczywistych zastosowaniach.
Wdrożenie tego procesu w internecie jest jednak trudne. Jeśli używasz słownika do kompresowania zasobu, musisz mieć ten sam słownik, aby go zdekompresować. Ten proces był już wcześniej stosowany w internecie (SDCH), ale jego bezpieczne wdrożenie było trudne. Ta najnowsza propozycja dotycząca kompresji za pomocą słownika współdzielonego rozwiązuje te problemy, a jednocześnie zapewnia znaczną korzyść zarówno w przypadku zasobów statycznych, jak i dynamicznych.
Jak Chrome informuje o obsłudze słowników współdzielonych
Wszystkie przeglądarki informują o obsługiwanych algorytmach kompresji za pomocą Accept-Encoding nagłówka żądania. Zawartość nagłówka to rozdzielona przecinkami lista obsługiwanych kodowań:
Accept-Encoding: gzip, br, zstd
Ten konkretny nagłówek Accept-Encoding informuje, że przeglądarka wysyłająca żądanie zasobu obsługuje algorytmy kompresji gzip, Brotli i ZStandard. Serwer WWW odpowiadający na żądanie może wtedy zdecydować, którego algorytmu użyć.
Gdy włączona jest obsługa słownika współdzielonego, a dla zasobu dostępny jest odpowiedni słownik, do nagłówka Accept-Encoding dodawane są dodatkowe tokeny. Te tokeny to br-d dla Brotli i zstd-d dla Zstandard. Chrome będzie też zawierać skrót dostępnego słownika, co opisujemy poniżej.
Accept-Encoding: gzip, br, zstd, br-d, zstd-d
Available-Dictionary: :pZGm1Av0IEBKARczz7exkNYsZb8LzaMrV7J32a2fFG4=:
Jeśli serwer WWW jest skonfigurowany tak, aby rozpoznawać ten token, i rozpoznaje słownik, może odpowiedzieć na to żądanie zasobem skompresowanym za pomocą słownika dla odpowiedniego kodowania. Sposób, w jaki to się odbywa w praktyce, zależy od tego, czy żądanie dotyczy zasobu statycznego czy dynamicznego.
Kompresja za pomocą słownika współdzielonego w przypadku zasobów statycznych
Statyczny zasób strony to taki, który zawsze generuje tę samą odpowiedź na żądany adres URL. Typowe przykłady statycznych zasobów strony, które można skompresować, to pliki JavaScript i CSS. Te zasoby są zwykle wersjonowane na potrzeby buforowania w jakiś sposób – czasami za pomocą skrótu zawartości pliku w nazwie pliku (np. styles.abcd1234.css) lub innej metody identyfikacji zasobu. Te typy zasobów doskonale nadają się do kompresji różnicowej, którą zapewniają słowniki współdzielone, ponieważ zasoby statyczne są często buforowane przez długi czas i są aktualizowane z pewną częstotliwością.
Słownik można określić dla zasobu statycznego, ustawiając dla niego nagłówek odpowiedzi Use-As-Dictionary. Nagłówek przyjmuje jedną z kilku par klucz-wartość, ale jedyną wymaganą jest match, która akceptuje URLPattern składnię określającą ścieżkę zasobu, w której ma być używany słownik:
Use-As-Dictionary: match="/dist/styles.*.css"
Nagłówek Use-As-Dictionary to mechanizm, który ma zastosowanie do przyszłych wersji zasobu pasujących do wzorca określonego w tym nagłówku. Załóżmy, że Twoja witryna zawiera wszystkie style w jednym pliku CSS. Dla uproszczenia załóżmy, że pierwsza wersja tego zasobu znajduje się pod adresem /dist/styles.v1.css i jest wysyłana z nagłówkiem odpowiedzi Use-As-Dictionary zawierającym wartość match równą /dist/styles.*.css.
Po pewnym czasie aktualizujesz CSS swojej witryny i udostępniasz jego nową wersję znajdującą się pod adresem /dist/styles.v2.css. Ponieważ wartość match użyta w nagłówku odpowiedzi Use-As-Dictionary z poprzedniej wersji ma zastosowanie do tego żądania, przeglądarka wyśle nagłówek Available-Dictionary zawierający skrót słownika zakodowany jako sekwencja bajtów pola strukturalnego:
Accept-Encoding: gzip, br, zstd, br-d, zstd-d
Available-Dictionary: :pZGm1Av0IEBKARczz7exkNYsZb8LzaMrV7J32a2fFG4=:
W tym momencie serwer musi skonfigurować kompresję po swojej stronie, aby zapewnić użycie pasującego słownika. Zasób skompresowany za pomocą tego słownika zostanie wysłany, a do jego zdekompresowania zostanie użyty dostępny słownik w pamięci podręcznej przeglądarki użytkownika.
Jeśli często udostępniasz nowy kod w swojej witrynie, kompresja różnicowa może być bardzo przydatna. Proces jest jednak elastyczny. Jeśli przeglądarka nie stwierdzi, że w pamięci podręcznej przeglądarki użytkownika dostępny jest słownik, nie określi dodatkowych tokenów br-d ani zstd-d w nagłówku Accept-Encoding. W takim przypadku stosowany jest standardowy proces kompresji.
Kompresja za pomocą słownika współdzielonego w przypadku zasobów dynamicznych
Zasoby dynamiczne mogą też korzystać z kompresji za pomocą słownika współdzielonego. Zasoby dynamiczne to takie, które zmieniają się w zależności od kontekstu, np. witryna z wiadomościami, w której strona główna jest często aktualizowana w miarę pojawiania się nowych informacji. Dokumenty HTML są często zasobami dynamicznymi. W takich przypadkach słownik może zawierać większość wspólnej struktury HTML witryny i kodu szablonu, co prowadzi do skompresowanych stron, w których wysyłane są tylko unikalne części każdej strony.
Ze względu na charakter zasobów generowanych dynamicznie słownik musi zostać wczytany na kliencie, aby można go było później użyć. Wczytywanie słownika z wyprzedzeniem oznacza, że stosowanie kompresji za pomocą słownika współdzielonego do zasobów dynamicznych jest spekulatywne. W takich przypadkach mamy nadzieję, że Twoja witryna będzie miała wystarczająco duży ruch, aby koszt słownika mógł zostać zamortyzowany w dużej liczbie nawigacji. Jeśli zdecydujesz się na to, pierwszym krokiem jest określenie lokalizacji słownika za pomocą elementu <link> w kodzie HTML strony:
<link rel="dictionary" href="/dictionary.dat">
Gdy Chrome napotka ten element <link>, może pobrać słownik, gdy strona jest nieaktywna, i z niskim priorytetem, aby uniknąć konfliktu przepustowości. Odpowiedź na słownik musi zawierać nagłówek Use-As-Dictionary i określać, do której ścieżki zasobu dynamicznego ma zastosowanie:
Use-As-Dictionary: match="/product/*"
Od tego momentu proces jest w dużej mierze taki sam jak w przypadku zasobów statycznych. Przeglądarka zobaczy, że słownik ma zastosowanie do pasujących zasobów, i dołączy do żądania nagłówek Available-Dictionary ze skrótem zawartości słownika, podobnie jak w przypadku zasobów statycznych opisanym wcześniej.
Kompresowanie zasobów statycznych podczas kompilacji
Jeśli znasz narzędzia do łączenia plików, możesz znać różne wtyczki, które mogą kompresować zasoby podczas kompilacji, a następnie udostępniać te skompresowane zasoby. Apache umożliwia np. używanie dyrektyw do udostępniania tych wstępnie skompresowanych zasobów w momencie żądania.
Większość narzędzi do łączenia plików opartych na Node.js, które obsługują kompresję, korzysta z wbudowanej biblioteki Zlib Node.js. Zlib obsługuje Brotli, a narzędzia do łączenia plików, które z niej korzystają, zwykle oferują interfejs do przekazywania opcji bezpośrednio do Zlib, która obsługuje kompresję wspomaganą przez słownik. Oto kilka narzędzi do łączenia plików, które obsługują używanie słowników:
CompressionWebpackPluginw webpacku, za pomocą interfejsucompressionOptions.rollup-plugin-brotlioferuje konfiguracjęoptions, która jest przekazywana bezpośrednio do Zlib w Node.js, gdzie można określić słowniki.- Wtyczka innej firmy
esbuild-plugin-compressdo esbuild też zapewnia dostęp do opcji Zlib w Node.js.
Pamiętaj, że dostępne słowniki dla dowolnej wersji zasobu mogą używać jednej z poprzednich wersji zasobu. Oznacza to, że musisz przeanalizować ruch użytkowników i odpowiednio zaplanować działania. Staraj się zachować równowagę i generować zasoby, które przynoszą jak największe korzyści jak największej liczbie powracających użytkowników. Dostawcy CDN eksperymentują obecnie z kompresją za pomocą słownika współdzielonego. Żadne implementacje nie są jeszcze dostępne do publicznego użytku, ale spodziewamy się, że to się zmieni.
Spróbuj!
Zintegrowanie kompresji za pomocą słownika współdzielonego z dotychczasowymi możliwościami kompresji w przeglądarce może znacznie poprawić wydajność wczytywania witryn, które często udostępniają zaktualizowany kod produkcyjny i otrzymują duży ruch od powracających użytkowników. Jeśli chcesz wypróbować kompresję za pomocą słownika współdzielonego, masz 2 możliwości:
- Jeśli chcesz tylko poeksperymentować z kompresją za pomocą słownika współdzielonego, aby sprawdzić, jak działa, możesz włączyć eksperymentalną funkcję Transport słownika kompresji na stronie
chrome://flags. - Jeśli chcesz wypróbować tę funkcję w swojej witrynie produkcyjnej i sprawdzić, jak kompresja za pomocą słownika współdzielonego może przynieść korzyści prawdziwym użytkownikom, zarejestruj się w testach origin, aby uzyskać token, i przeczytaj, jak działają testy origin.
Podsumowanie
Bardzo cieszymy się z tego ważnego postępu w technologii kompresji w internecie i z tego, jak bardzo może on przyspieszyć działanie aplikacji, z których ludzie korzystają na co dzień. Zachęcamy do wypróbowania tej funkcji, a przede wszystkim do podzielenia się z nami swoimi opiniami. Jeśli znajdziesz błąd, zgłoś go na stronie crbug.com. Dodatkowe materiały i narzędzia znajdziesz na stronie use-as-dictionary.com. Jeśli chcesz dowiedzieć się więcej o tym, jak to wszystko działa, dobrym następnym krokiem będzie zapoznanie się z wyjaśnieniem.