Pakiet Next.js do zarządzania bibliotekami innych firm

W 2021 r. zespół Chrome Aurora wprowadził komponent skryptu, aby poprawić wydajność wczytywania skryptów innych firm w Next.js. Od czasu jego wprowadzenia rozszerzyliśmy jego możliwości, aby ułatwić i przyspieszyć wczytywanie zasobów innych firm.

W tym poście na blogu omawiamy nowe funkcje, które wprowadziliśmy, w tym przede wszystkim bibliotekę @next/third-parties, a także zapowiadamy przyszłe inicjatywy.

Wpływ skryptów innych firm na skuteczność

41% wszystkich żądań zewnętrznych w witrynach Next.js to skrypty. W odróżnieniu od innych typów treści pobieranie i wykonywanie skryptów może zająć sporo czasu, co może blokować renderowanie i opóźniać interakcje z użytkownikiem. Dane z raportu na temat użytkowania Chrome (CrUX) wskazują, że witryny Next.js, które wczytują więcej skryptów innych firm, mają niższe współczynniki interakcji do następnego wyrenderowania (INP)największego wyrenderowania treści (LCP).

Wykres słupkowy pokazujący spadek odsetka aplikacji Next.js osiągających dobre wyniki w przypadku INP i LCP w zależności od liczby wczytanych zasobów stron trzecich
Raport CrUX z grudnia 2023 r. (110 823 witryn)

Korelacja widoczna na tym wykresie nie oznacza związku przyczynowo-skutkowego. Jednak eksperymenty lokalne dostarczają dodatkowych dowodów na to, że skrypty zewnętrzne w znacznym stopniu wpływają na wydajność strony. Na przykład na wykresie poniżej porównano różne rodzaje danych dostępnych w laboratoriach, gdy kontener Menedżera tagów Google – zawierający 18 losowo wybranych tagów – został dodany do Taksonomii, popularnej przykładowej aplikacji Next.js.

Wykres słupkowy przedstawiający różnice w różnych danych testowych podczas wczytywania witryny z Menedżerem tagów Google i bez niego
WebPageTest (mobilna sieć 4G – Wirginia, USA)

Szczegółowe informacje o sposobie pomiaru tych wartości znajdziesz w dokumentacji WebPageTest. Na pierwszy rzut oka widać, że na wszystkie te dane laboratoryjne wpływa kontener Menedżera tagów Google. Na przykład wskaźnik Total Blocking Time (TBT) – przydatna wartość zastępcza, która przybliża wartość INP – wzrósł prawie 20-krotnie.

Komponent skryptu

Gdy wprowadziliśmy komponent <Script> w Next.js, zadbaliśmy o to, aby był on dostępny za pomocą przyjaznego dla użytkownika interfejsu API, który przypomina tradycyjny element <script>. Dzięki temu deweloperzy mogą umieszczać skrypt firmy zewnętrznej w dowolnym komponencie aplikacji, a Next.js zajmie się sekwencyjnością skryptu po załadowaniu kluczowych zasobów.

<!-- By default, script will load after page becomes interactive -->
<Script src="https://example.com/sample.js" />

<!-- Script is injected server-side and fetched before any page hydration occurs -->
<Script strategy=”beforeInteractive” src="https://example.com/sample.js" />

<!-- Script is fetched later during browser idle time -->
<Script strategy=”lazyOnload” src="https://example.com/sample.js" />

Składnik <Script> jest używany przez dziesiątki tysięcy aplikacji Next.js, w tym popularne witryny, takie jak Patreon, Target i Notion. Pomimo skuteczności tej metody niektórzy deweloperzy wyrazili obawy dotyczące następujących kwestii:

  • Gdzie umieścić komponent <Script> w aplikacji Next.js, przestrzegając różnych instrukcji instalacji od różnych dostawców zewnętrznych (funkcje dla dewelopera).
  • Która strategia wczytywania jest optymalna w przypadku różnych skryptów zewnętrznych (wygoda użytkownika).

Aby rozwiązać oba te problemy, wprowadziliśmy @next/third-parties – specjalistyczną bibliotekę oferującą zestaw zoptymalizowanych komponentów i narzędzi dostosowanych do potrzeb popularnych innych firm.

Ułatwienie deweloperom zarządzania bibliotekami innych firm

W znacznym odsetku witryn Next.js jest stosowanych wiele skryptów innych firm, przy czym najpopularniejsze jest Menedżer tagów Google – używany jest odpowiednio 66% witryn. @next/third-parties opiera się na komponencie <Script>, wprowadzając owijarki wyższego poziomu, które mają uprościć korzystanie z tych typowych zastosowań.

import { GoogleAnalytics } from "@next/third-parties/google";

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>{children}</body>
      <GoogleTagManager gtmId="GTM-XYZ" />
    </html>
  );
}

Google Analytics to kolejny często używany skrypt zewnętrzny (52% witryn Next.js), który ma też swój własny komponent.

import { GoogleAnalytics } from "@next/third-parties/google";

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>{children}</body>
      <GoogleAnalytics gaId="G-XYZ" />
    </html>
  );
}

@next/third-parties upraszcza proces wczytywania często używanych skryptów, ale zwiększa też możliwości opracowywania narzędzi dla innych kategorii zewnętrznych, takich jak umieszczanie elementów. Na przykład w 8%4% witryn Next.js odpowiednio wstawiane są Mapy Google i YouTube. Wprowadziliśmy też komponenty, które ułatwiają ich wczytywanie.

import { GoogleMapsEmbed } from "@next/third-parties/google";
import { YouTubeEmbed } from "@next/third-parties/google";

export default function Page() {
  return (
    <>
      <GoogleMapsEmbed
        apiKey="XYZ"
        height={200}
        width="100%"
        mode="place"
        q="Brooklyn+Bridge,New+York,NY"
      />
      <YouTubeEmbed videoid="ogfYd705cRs" height={400} params="controls=0" />
    </>
  );
}

Interfejs użytkownika: szybsze ładowanie bibliotek innych firm

W idealnym świecie każda powszechnie używana biblioteka zewnętrzna byłaby w pełni zoptymalizowana, co uczyniłoby niepotrzebnymi wszelkie abstrakcje poprawiające jej wydajność. Do tego czasu możemy jednak spróbować poprawić wygodę użytkowników dzięki integracji z popularnymi platformami, takimi jak Next.js. Możemy eksperymentować z różnymi technikami wczytywania, dbać o to, aby skrypty były ustawione w odpowiedni sposób, a ostatecznie udostępnić swoją opinię dostawcom zewnętrznym, aby zachęcić do wprowadzania zmian na wcześniejszym etapie.

Weźmy na przykład osadzenie filmu z YouTube. Niektóre alternatywne implementacje mają znacznie lepszą skuteczność niż wbudowane. Obecnie komponent <YouTubeEmbed> eksportowany przez @next/third-parties korzysta z kodu lite-youtube-embed, który po przedstawieniu porównania Next.js z projektu „Hello, World” Next.js działa znacznie szybciej.

GIF przedstawiający porównanie wczytania strony między komponentem YouTube do umieszczenia na stronie a zwykłym elementem iframe YouTube
WebPageTest (mobilna sieć 4G – Wirginia, USA)

Podobnie w przypadku Map Google domyślnym atrybutem umieszczania jest loading="lazy", aby mapy wczytywały się tylko wtedy, gdy znajdują się w określonej odległości od widocznego obszaru. Może się wydawać, że jest to oczywisty atrybut do uwzględnienia, zwłaszcza że dokumentacja Map Google zawiera go w przykładowym fragmencie kodu, ale tylko 45% witryn Next.js, które zawierają mapy Google, używa loading="lazy".

Uruchamianie skryptów innych firm w środowisku internetowym

Jedną z zaawansowanych technik, które badamy w usłudze @next/third-parties, jest ułatwienie przekazywania skryptów innych firm do instancji internetowej. Jest to rozwiązanie popularyzowane przez biblioteki takie jak Partytown. Może ono znacznie ograniczyć wpływ skryptów innych firm na wydajność strony, ponieważ przenosi je całkowicie poza główny wątek.

Ten animowany GIF pokazuje różnice w czasie blokowania przez główny wątek długich zadań i czas blokowania przez niego wątku, gdy stosujesz różne strategie <Script> do kontenera GTM w witrynie Next.js. Pamiętaj, że przełączanie się między opcjami strategii opóźnia tylko czas wykonywania tych skryptów, a przeniesienie ich do web workera całkowicie eliminuje ich czas w głównym wątku.

GIF pokazujący różnice w czasie blokowania głównego wątku w przypadku różnych strategii skryptu
WebPageTest (Mobile 4G – Wirginia USA)

W tym konkretnym przykładzie przeniesienie wykonania kontenera Menedżera tagów Google i powiązanych z nim skryptów tagów do web workera zmniejszyło TBT o 92%.

Warto zauważyć, że jeśli nie zarządzasz tą metodą ostrożnie, może ona dyskretnie uszkodzić wiele skryptów innych firm, co utrudnia debugowanie. W najbliższych miesiącach sprawdzimy, czy komponenty innych firm oferowane przez @next/third-parties działają prawidłowo podczas uruchamiania w środowisku internetowym. Jeśli tak, chcemy udostępnić deweloperom prosty i opcjonalny sposób korzystania z tej metody.

Dalsze kroki

W trakcie tworzenia tego pakietu okazało się, że trzeba scentralizować rekomendacje dotyczące ładowania z użyciem zewnętrznych bibliotek, aby inne platformy mogły korzystać z tych samych podstawowych technik. W efekcie stworzyliśmy bibliotekę Third Party Capital, która wykorzystuje format JSON do opisywania technik ładowania z użyciem zewnętrznych zasobów. Obecnie stanowi ona podstawę dla @next/third-parties.

W następnych krokach będziemy nadal ulepszać komponenty udostępniane w ramach Next.js, a także zwiększać nasze wysiłki, aby uwzględniać podobne narzędzia w innych popularnych platformach i platformach CMS. Obecnie współpracujemy z utrzymawcami Nuxt i planujemy w najbliższej przyszłości udostępnić podobne narzędzia innych firm dostosowane do ich ekosystemu.

Jeśli jedna z aplikacji innych firm używanych w aplikacji Next.js jest obsługiwana przez @next/third-parties, zainstaluj pakiet i spróbuj go użyć. Chętnie poznamy Twoją opinię na GitHub.