Pakiet Next.js do zarządzania bibliotekami innych firm

W 2021 r. zespół Chrome Aurora wprowadził komponent skryptu, aby zwiększyć wydajność wczytywania skryptów innych firm w Next.js. Od momentu wprowadzenia na rynek zwiększyliśmy jego możliwości, aby ułatwić i przyspieszyć ładowanie zasobów innych firm.

W tym poście znajdziesz omówienie nowo udostępnionych funkcji, a w szczególności biblioteki @next/third-partyies, oraz zarys przyszłych inicjatyw w naszym harmonogramie.

wpływ na wydajność skryptów zewnętrznych.

41% wszystkich żądań zewnętrznych w witrynach Next.js to skrypty. W przeciwieństwie do innych typów treści pobieranie i wykonywanie skryptów może zająć dużo czasu, co może blokować renderowanie i opóźniać interaktywność użytkownika. Dane z Raportu na temat użytkowania Chrome (CrUX) pokazują, że witryny Next.js, które wczytują więcej skryptów zewnętrznych, mają niższe współczynniki akceptacji interakcji z kolejnym wyrenderowaniem (INP) i największym wyrenderowaniem treści (LCP).

Wykres słupkowy przedstawiający spadek odsetka użytkowników Next.js, którzy uzyskali dobre wyniki INP i LCP, proporcjonalnie do liczby wczytanych aplikacji zewnętrznych.
Raport na temat użytkowania Chrome z grudnia 2023 r. (110 823 witryn)

Związek zaobserwowany na tym wykresie nie sugeruje związku przyczynowo-skutkowego. Eksperymenty lokalne dostarczają jednak dodatkowych dowodów na to, że skrypty innych firm w znacznym stopniu wpływają na wydajność strony. Na wykresie poniżej widać na przykład porównanie różnych danych dostępnych w Laboratorium, gdy kontener Menedżera tagów Google – zawierający 18 losowo wybranych tagów – został dodany do popularnej przykładowej aplikacji Next.js – Taxonomy.

Wykres słupkowy pokazujący różnicę w danych dostępnych w laboratorium, gdy witryna jest wczytana za pomocą Menedżera tagów Google i bez niego.
WebPageTest (Mobile 4G – Virginia USA)

Dokumentacja WebPageTest zawiera szczegółowe informacje o sposobie pomiaru tych czasów. Na pierwszy rzut oka widać, że kontener Menedżera tagów Google wpływa na wszystkie te dane. Na przykład całkowity czas blokowania (TBT) – przydatny moduł proxy o wartości INP – zwiększył się niemal 20-krotnie.

Komponent skryptu

Wprowadzając komponent <Script> w Next.js, zadbaliśmy o to, aby wprowadzić go w ramach łatwego w użyciu interfejsu API, który bardzo przypomina tradycyjny element <script>. Dzięki niemu programiści mogą współdzielić skrypt zewnętrzny w dowolnym komponencie w aplikacji, a Next.js odpowiada za sekwencjonowanie skryptu po wczytaniu krytycznych 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" />

Dziesiątki tysięcy aplikacji Next.js, w tym popularne witryny, takie jak Patreon, Target i Notion, korzystają z komponentu <Script>. Pomimo tego, że funkcja ta jest niezawodna, niektórzy deweloperzy mają obawy w związku z tymi kwestiami:

  • Gdzie w aplikacji Next.js umieścić komponent <Script>, stosując się do różnych instrukcji instalacji stosowanych przez różnych dostawców zewnętrznych (dla programistów).
  • Która strategia wczytywania jest optymalna w przypadku różnych skryptów zewnętrznych (wygoda użytkowników).

Aby sprostać obu tym obawom, uruchomiliśmy @next/third-parties – specjalistyczną bibliotekę oferującą zestaw zoptymalizowanych komponentów i narzędzi dostosowanych do popularnych firm zewnętrznych.

Dla programistów: łatwiejsze zarządzanie bibliotekami innych firm

W znacznej części witryn Next.js używanych jest wiele skryptów firm zewnętrznych, przy czym największą popularnością cieszy się Menedżer tagów Google. Korzysta z nich odpowiednio 66% witryn. @next/third-parties uzupełnia komponent <Script> przez wprowadzenie kodów wyższego poziomu, które ułatwiają korzystanie z komponentów w tych typowych przypadkach użycia.

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 – inny często używany skrypt firmy zewnętrznej (52% witryn Next.js) również ma własny, dedykowany 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 rozszerza nasze możliwości tworzenia narzędzi dla innych kategorii zewnętrznych, takich jak umieszczone elementy. Umieszczone elementy w Mapach Google i YouTube są na przykład używane odpowiednio w 8% i 4% witryn Next.js. Udostępniamy 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" />
    </>
  );
}

Wygoda użytkownika: szybsze wczytywanie bibliotek zewnętrznych

W idealnym świecie każda powszechnie używana biblioteka zewnętrzna byłaby w pełni zoptymalizowana, dzięki czemu wszelkie abstrakcje poprawiające wydajność byłyby niepotrzebne. Do tego czasu możemy jednak spróbować poprawić wrażenia użytkowników korzystających z integracji z popularnymi platformami, takimi jak Next.js. Możemy eksperymentować z różnymi technikami wczytywania, dbać o odpowiednią sekwencję skryptów i w końcu przekazywać nasze opinie dostawcom zewnętrznym, aby zachęcić ich do wprowadzania zmian na etapie początkowym.

Weźmy na przykład umieszczanie filmów z YouTube na stronach. Niektóre alternatywne implementacje mają znacznie większą skuteczność niż umiejscowiona reklama natywna. Obecnie komponent <YouTubeEmbed> wyeksportowany przez @next/third-parties używa modułu lite-youtube-embed, który w przypadku porównania z operatorem „Hello, World” Next.js wczytuje się znacznie szybciej.

GIF przedstawiający porównanie czasu wczytywania strony między komponentem YouTube umieszczanym na stronie a zwykłym elementem iframe YouTube
WebPageTest (Mobile 4G – Virginia USA)

Podobnie w Mapach Google uwzględniamy atrybut loading="lazy" jako domyślny atrybut umieszczonej reklamy, aby mieć pewność, że mapa wczytuje się tylko wtedy, gdy znajduje się w określonej odległości od widocznego obszaru. Może się to wydawać oczywistym atrybutem, który warto dodać – zwłaszcza że jest on uwzględniony w dokumentacji Map Google w przykładowym fragmencie kodu. Jednak tylko 45% witryn Next.js zawierających Mapy Google korzysta z elementu loading="lazy".

Uruchamianie skryptów innych firm w instancjach roboczych

Jedną z zaawansowanych metod, którą omawiamy w usłudze @next/third-parties, jest ułatwienie przenoszenia skryptów innych firm do instancji roboczych. Spopularyzowane przez takie biblioteki jak Partytown, mogą znacznie zmniejszyć wpływ skryptów innych firm na wydajność strony, całkowicie przenosząc je z wątku głównego.

Poniższy animowany GIF pokazuje różnice w czasie wykonywania długich zadań i czasu blokowania w wątku głównym w przypadku stosowania różnych strategii <Script> do kontenera Menedżera tagów Google w witrynie Next.js. Pamiętaj, że chociaż przełączanie opcji strategii tylko opóźnia czas wykonania tych skryptów, przeniesienie ich do instancji roboczej eliminuje czas spędzany w wątku głównym.

GIF przedstawiający różnice w czasie blokowania wątków głównych w przypadku różnych strategii dotyczących skryptu
WebPageTest (Mobile 4G – Virginia USA)

W tym przykładzie przeniesienie wykonania kontenera Menedżera tagów Google i powiązanych z nim skryptów tagów do skryptu roboczego zmniejszyło wartość TBT o 92%.

Pamiętaj, że jeśli nie będziesz odpowiednio zarządzać tą techniką, może ona dyskretnie uszkodzić wiele skryptów zewnętrznych, co utrudnia debugowanie. W najbliższych miesiącach sprawdzimy, czy komponenty zewnętrzne oferowane przez usługę @next/third-parties działają prawidłowo w programach roboczych. Jeśli tak, postaramy się udostępnić deweloperom prosty i opcjonalny sposób korzystania z tej metody.

Dalsze kroki

W trakcie tworzenia tego pakietu stało się oczywiste, że trzeba scentralizować rekomendacje dotyczące wczytywania z usług zewnętrznych, aby inne platformy również mogły korzystać z tych samych podstawowych technik. Następnie stworzyliśmy External Party Capital – bibliotekę, która wykorzystuje JSON do opisywania zewnętrznych technik wczytywania danych. Obecnie są one podstawą dla @next/third-parties.

W ramach kolejnych kroków będziemy nadal skupiać się na ulepszaniu komponentów dostępnych dla Next.js. Będziemy też rozszerzać nasze starania o uwzględnienie podobnych narzędzi w innych popularnych platformach i platformach CMS. Obecnie współpracujemy z firmami obsługującymi Nuxt. W najbliższej przyszłości planujemy udostępnić podobne narzędzia zewnętrzne dostosowane do ich ekosystemu.

Jeśli @next/third-parties obsługuje usługę firmy zewnętrznej, której używasz w aplikacji Next.js, zainstaluj pakiet i spróbuj. Chętnie poznamy Twoją opinię o GitHub.