Kategoria:Performance

Optymalizacja zewnętrznych skryptów przez Web Workery, Partytown i Next.js

  • Czas potrzebny na przeczytanie:4 minuty
  • Opublikowane:

Performance w 2022 roku to jedna z najbardziej kluczowych rzeczy podczas budowania stron i aplikacji webowych. Poza najważniejszymi odczuciami użytkownika, wiemy, że Google bierze pod uwagę metryki wydajności podczas pozycjonowania. Czasem nie ważne jak bardzo byśmy się starali, pomimo optymalizacji obrazków i fontów, wynik Lighthouse dla naszego projektu może świecić się cały na czerwono... Zewnętrzne skrypty mogą być powodem!

Problem

Ładujesz Google Analytics, Tag Manager, skrypty Facebooka, dymka wiadomości... Uff, sporo tego, prawda? A teraz wyobraź sobie, że to wszystko ląduje w głównym wątku razem z całym potrzebnym JavaScriptem do prawidłowego funkcjonowania Twojej aplikacji. Nie brzmi to najlepiej. Przy dobrym połączeniu sieciowym ten problem może nie mieć aż takiego znaczenia, ale jeśli spojrzymy na to, jak działają strony na urządzeniach mobilnych, to zaczynamy dostrzegać pewne komplikacje.

Optymalizacja skryptów w Next.js

Pierwszym krokiem by usprawnić proces pobierania skryptów, byłoby dodanie atrybutków async / defer do tagu <script>. Dzięki temu nie blokujemy parsowania dokumentu HTML. Przydałoby się również dodanie preconnect i dns prefetch, dzięki nim szybciej zaadresujemy chęć pobrania czegoś z zewnętrznej domeny. To brzmi jak... kawałek niepotrzebnego boilerplate'u. Na szczęście twórcy Next.js zadbali o Developer Experience i wprowadzili ich autorski komponent <Script>:

<Script src="..." strategy="beforeInteractive" />
<Script src="..." strategy="afterInteractive" />
<Script src="..." strategy="lazyOnload" />
  1. beforeInteractive - przeciwieństwo tego, z czym chcemy dziś walczyć. Krytyczne skrypty, które chcemy odpalać jeszcze przed tym, jak strona będzie interaktywna
  2. afterInteractive - ładuje skrypty tuż po osiągnięciu pełnej interaktywności strony. Sprawdzi się np. dla Google Analytics / Tag Manager
  3. lazyOnload - ostatnie skrypty w kolejce. Jak już się wszystko załadowało, to lecimy właśnie z nimi. Idealne dla rzeczy, które mogą być ładowane "w tle", np. dymek wiadomości

To wszystko brzmi naprawdę świetnie i faktycznie Next robi za nas zajebistą robotę w optymalizacji skryptów. Wady? Nadal obciążamy główny wątek.

Web Workery i Partytown

Rozwiązanie naszego problemu? Web Workery. Działają one z dala od głównego wątku, nie ingerując w skrypty potrzebne do interaktywności strony...Hola hola, Web Workery? Przecież system komunikacji pomiędzy Web Workerem, a głównym wątkiem jest asynchroniczny, przez co Web Worker nie ma bezpośredniego dostępu do API przeglądarki. Jest to dużym problemem dla zewnętrznych skryptów, bowiem działają one często w oparciu o DOM.

Partytown to leciutka biblioteka, która rozwiązuje ten problem.

Przebieg 'normalnych' skryptów przez główny wątek, kontra wykorzystanie Web Workerów do przepływu zewnętrznych skryptów

Pozwala ona na synchroniczną komunikację Web Workera z głównym wątkiem, jest swego rodzaju proxy. Poza dostępem do DOM, mamy możliwość zarządzania dostępem do niektórych API, np. możemy zablokować dostęp do document.cookie, czy uniemożliwić zapisywanie skryptowi do localStorage.

Partytown i Next.js w praktyce

Partytown to biblioteka typu framework agnostic, działa ze zwykłym HTML, React, Nuxt, Remix oraz od niedawna z dedykowanym komponentem <Script> w Next. Zacznijmy od instalacji:

Next.js "natywnie" wspiera Partytown dopiero w wersji eksperymentalnej, żeby z niej skorzystać musimy uzupełnić konfigurację:

Zostało nam tylko odpalenie projektu i wykorzystanie strategy="worker" w komponencie <Script>, od teraz nasz główny wątek będzie wolny od skryptów third-party.

Debugowanie

Chociaż Partytown nie wymaga żadnej dodatkowej konfiguracji, to przydatna może okazać opcja debug. Aby ją odblokować, musimy dodać skrypt z atrybutem data-partytown-config do Next Document:

pages/_document.tsx

import { Html, Head, Main, NextScript } from 'next/document';

export default function Document() {
  return (
    <Html>
      <Head>
        <script
          data-partytown-config
          dangerouslySetInnerHTML={{
            __html: `
              partytown = {
                lib: "/_next/static/~partytown/",
                debug: true
              };
            `,
          }}
        />
      </Head>
      <body>
        <Main />
        <NextScript />
      </body>
    </Html>
  );
}

Jeśli coś pójdzie nie po naszej myśli, to dzięki debug: true zobaczymy to zapewne w logach:

Logowanie dla trybu 'debug: true' w Partytown

Wady Partytown

To wszystko wydaje się być zbyt piękne, prawda? Jak wszystko w programowaniu, Partytown posiada wiele wad i ograniczeń. Dla mnie największym blockerem jest to, że biblioteka jest bardzo świeżym i niedojrzałym rozwiązaniem. Jakie trade-offy się kryją po stronie technicznej?

  • biblioteka nie jest przyjazna dla skryptów operujących na DOM i wprowadzających interaktywność z UI. Wszystkie operacje na DOM w Workerze są celowo opóźniane, przez co będą wolniejsze od tradycyjnego operowania na głównym wątku.
  • konieczność wprowadzanie proxy żądania dla zewnętrznych skryptów, które nie korzystają z nagłówka Access-Control-Allow-Origin: *.
  • brak wsparcia dla event.preventDefault().
  • ograniczenia w obsłudze ciasteczek i localStorage dla cross-origin iframe

Partytown vs Next Script

Pytanie, które narodziło się w mojej głowie, kiedy poznawałem Partytown, to:

"Kiedy tak właściwie korzystać ze zwykłych skryptów, a kiedy je delegować do Web Workera?".

Pomijając już niedojrzałość tego rozwiązania, Partytown sprawdzi się świetnie dla skryptów, które mogą działać nieco "w tle" - Google Analytics, czy Facebook Pixel to dobre przykłady. Wszystkie inne skrypty, które wymagają interakcji z DOM, warto wziąć pod lupę. Jeśli tych operacji jest trochę, to raczej bez zastanowienia skłaniałbym się ku normalnym skryptom w Next - będzie po prostu szybciej 🚀

Podsumowanie

Partytown pomimo wszystkich swoich wad, jest naprawdę bardzo ciekawym narzędziem do optymalizacji zewnętrznych skryptów - w końcu dajemy odetchnąć naszemu głównemu wątkowi!

Bardzo się cieszę, że twórcy bibliotek coraz większy nacisk kładą właśnie na performance, to realnie przekłada się na odczucia użytkownika :)

A Ty co sądzisz o Partytown?

Źródła

O autorze

Olaf Sulich

Olaf jest Frontend Developerem, blogerem i nosi rybacki kapelusz 🎩 Pisze o wszystkim co związane z frontendem, ale nie boi się backendu i designów 🦾 Ma głowę pełną pomysłów i nadzieję, że znajdziesz tutaj coś dla siebie!

Dołącz do społeczności!

Bo w programowaniu liczą się ludzie

Wchodzę