サードパーティ ライブラリを管理するための Next.js パッケージ

2021 年、Chrome Aurora チームは Next.js でのサードパーティ スクリプトの読み込みパフォーマンスを向上させるために、スクリプト コンポーネントを導入しました。リリース以来、Google はサードパーティ リソースの読み込みをより簡単かつ迅速に行えるように機能を拡張してきました。

このブログ投稿では、Google がリリースした新しい機能、特に @next/third-parties ライブラリの概要と、ロードマップにおける今後の取り組みの概要を説明します。

サードパーティ スクリプトのパフォーマンスへの影響

Next.js サイトのすべてのサードパーティ リクエストの 41% がスクリプトです。他のコンテンツ タイプとは異なり、スクリプトはダウンロードと実行にかなりの時間がかかるため、レンダリングがブロックされ、ユーザーの操作が遅れる可能性があります。Chrome ユーザー エクスペリエンス レポート(CrUX)のデータによると、多くのサードパーティ スクリプトを読み込む Next.js サイトでは、Interaction to Next Paint(INP)Largest Contentful Paint(LCP)の合格率が低くなります。

読み込まれたサードパーティの数に比例して、INP スコアと LCP スコアが良好な Next.js の割合が減少していることを示す棒グラフ
2023 年 12 月の CrUX レポート(110,823 サイト)

このグラフに見られる相関は因果関係を示唆するものではありません。ただし、ローカルテストでは、サードパーティのスクリプトがページのパフォーマンスに大きな影響を与えることを示す証拠が得られます。たとえば、以下のグラフは、ランダムに選択された 18 個のタグで構成される Google タグ マネージャー コンテナが、よく使われている Next.js サンプルアプリである分類に追加された場合の、ラボのさまざまな指標を比較したものです。

サイトの読み込みに Google タグ マネージャーを使用した場合と使用しない場合での、ラボの各種指標の違いを示す棒グラフ
WebPageTest(Mobile 4G - Virginia USA)

これらの時間の測定方法について詳しくは、WebPageTest のドキュメントをご覧ください。ご覧のように、これらのラボの指標はすべて GTM コンテナの影響を受けています。たとえば、Total Blocking Time(TBT)(INP を近似する有用なラボ用プロキシ)では、約 20 倍の増加が確認されました。

スクリプト コンポーネント

<Script> コンポーネントは、Next.js でリリースする際、従来の <script> 要素によく似たユーザー フレンドリーな API を介して導入しました。これを使用することで、デベロッパーはアプリケーションの任意のコンポーネントにサードパーティのスクリプトを同じ場所に配置でき、Next.js は重要なリソースの読み込み後にスクリプトの順序付けを行います。

<!-- 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" />

PatreonTargetNotion などの一般的なサイトを含む数万の Next.js アプリケーションが <Script> コンポーネントを使用しています。一部のデベロッパーは、その効果にもかかわらず、次のような懸念を提起しています。

  • さまざまなサードパーティ プロバイダのさまざまなインストール手順に準拠しつつ、Next.js アプリ内の <Script> コンポーネントを配置する場所(デベロッパー エクスペリエンス)
  • さまざまなサードパーティ スクリプトに使用するのに最適な読み込み方法(ユーザー エクスペリエンス)

この両方の問題に対処するために、@next/third-parties をリリースしました。これは、人気のあるサードパーティ向けにカスタマイズされた、最適化されたコンポーネントとユーティリティのセットを提供する専用ライブラリです。

デベロッパー エクスペリエンス: サードパーティ ライブラリの管理を容易に

多くのサードパーティのスクリプトが Next.js サイトのかなりの割合で使用されています。Google タグ マネージャーが最も一般的で、それぞれ 66% のサイトで使用されています。@next/third-parties は、<Script> コンポーネントの上に構築されており、このような一般的なユースケースの使用を簡素化するように設計された高レベルのラッパーを導入しています。

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

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

広く使用されているもう 1 つのサードパーティ スクリプト(Next.js サイトの 52%)にも、Google アナリティクス専用の専用コンポーネントがあります。

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 により、よく使用されるスクリプトの読み込みプロセスが簡素化されるだけでなく、埋め込みなどの他のサードパーティ カテゴリのユーティリティ開発能力も拡張されます。たとえば、Google マップと YouTube の埋め込みはそれぞれ Next.js ウェブサイトの 8%4% で使用されています。また、読み込みを容易にするコンポーネントもリリースされています。

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" />
    </>
  );
}

ユーザー エクスペリエンス: サードパーティ ライブラリの読み込みを高速化

広く採用されているサードパーティ ライブラリはすべて完全に最適化され、パフォーマンスを向上させる抽象化は不必要になります。それが実現するまでの間は、Next.js などの一般的なフレームワークを通じて統合することで、ユーザー エクスペリエンスの向上を図ることができます。Google は、さまざまな読み込み手法を試し、スクリプトが正しく順序付けられていることを確認して、最終的にはフィードバックをサードパーティ プロバイダと共有して、アップストリームでの変更を推奨できます。

たとえば、YouTube の埋め込み動画を取り上げます。一部の代替実装では、ネイティブ埋め込みよりもパフォーマンスがはるかに優れています。現在、@next/third-parties によってエクスポートされる <YouTubeEmbed> コンポーネントでは、lite-youtube-embed が使用されています。「Hello, World」の Next.js の比較で示すと、読み込み時間が大幅に短縮されます。

YouTube Embed コンポーネントと通常の YouTube iframe のページ読み込みの比較を示す GIF
WebPageTest(Mobile 4G - Virginia USA)

同様に、Google マップでも、埋め込みのデフォルト属性として loading="lazy" を含め、ビューポートから一定の距離を超えた場合にのみ地図が読み込まれるようにしています。この属性を含めるべきことは明白なように思えるかもしれませんが、Google マップのドキュメントにはサンプルコード スニペットに含まれているため、特にそうですが、loading="lazy" を使用しているのは、Google マップを埋め込んでいる Next.js サイトの 45% のみです。

ウェブ ワーカーでのサードパーティ スクリプトの実行

@next/third-parties で検討している高度な手法の 1 つは、サードパーティのスクリプトをウェブワーカーに簡単にオフロードできるようにすることです。Partytown などのライブラリでよく使用されるこのライブラリは、メインスレッドから完全に移動することで、ページ パフォーマンスに対する影響を大幅に軽減できます。

次のアニメーション GIF は、Next.js サイト内の GTM コンテナにさまざまな <Script> 戦略を適用したときの、長いタスクとメインスレッドのブロック時間の違いを示しています。戦略オプションを切り替えると、スクリプトの実行タイミングが遅れるだけですが、スクリプトをウェブワーカーに移動すると、メインスレッドに費やす時間が完全になくなります。

Script 戦略の種類によるメインスレッドのブロック時間の違いを示す GIF
WebPageTest(Mobile 4G - Virginia USA)

この例では、GTM コンテナとそれに関連するタグ スクリプトの実行をウェブワーカーに移行することで、TBT が 92%削減されました。

この手法は慎重に管理しないと、多くのサードパーティ スクリプトが通知なく動作しなくなり、デバッグが困難になることに注意してください。今後数か月以内に、@next/third-parties で提供されるサードパーティ コンポーネントがウェブワーカーで実行されたときに正しく機能するかどうかを検証します。そのような場合、デベロッパーがこの手法を簡単に使用できる方法(オプション)の提供に取り組んでまいります。

次のステップ

このパッケージの開発過程で、サードパーティ読み込みの推奨事項を一元化して、使用されているのと同じ基盤手法を他のフレームワークでも恩恵を受けられるようにする必要があることが明らかになりました。これを受けて、Third Party Capital を作成しました。これは、JSON を使用してサードパーティの読み込み手法を記述するライブラリで、現在 @next/third-parties の基盤となっています。

次のステップとして、Next.js 用に提供されているコンポーネントの改良に引き続き注力し、他の一般的なフレームワークや CMS プラットフォームにも同様のユーティリティを含めるための取り組みを拡大していきます。現在、Nuxt の管理者と連携し、近日中に Nuxt のエコシステムに合わせてカスタマイズされた同様のサードパーティ ユーティリティをリリースする予定です。

Next.js アプリで使用しているサードパーティのいずれかが @next/third-parties でサポートされている場合は、パッケージをインストールして試してみましょう。GitHub でフィードバックをお寄せください。