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

2021 年、Chrome Aurora チームは、Next.js のサードパーティ スクリプトの読み込みパフォーマンスを改善するために スクリプト コンポーネントを導入しました。リリース以来、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 サンプルアプリである Taxonomy に追加した場合の各種 Labs 指標を比較したものです。

Google タグ マネージャーありの場合となしの場合で、サイトが読み込まれたときのさまざまなラボ指標の差異を示す棒グラフ
WebPageTest(モバイル 4G - 米国バージニア)

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

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

Next.js で <Script> コンポーネントをリリースした際は、従来の <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" />

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

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

これらの懸念の両方に対処するため、Google は @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>
  );
}

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

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 などの一般的なフレームワークを介して統合することで、ユーザー エクスペリエンスを改善できます。さまざまな読み込み手法をテストし、スクリプトが適切に順序付けられていることを確認できます。最終的には、サードパーティ プロバイダとフィードバックを共有して、アップストリームの変更を促進できます。

YouTube の埋め込みを例に考えてみましょう。一部の代替実装は、ネイティブ埋め込みよりもはるかに優れたパフォーマンスを発揮します。現在、@next/third-parties によってエクスポートされた <YouTubeEmbed> コンポーネントは lite-youtube-embed を使用しています。これは、「Hello, World」Next.js の比較で実証されているように、読み込みが大幅に高速です。

YouTube 埋め込みコンポーネントと通常の YouTube iframe のページ読み込みを比較した GIF
WebPageTest(モバイル 4G - 米国バージニア)

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

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

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

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

さまざまなスクリプト戦略におけるメインスレッドのブロック時間の違いを示す GIF
WebPageTest(モバイル 4G - 米国バージニア)

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

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

次のステップ

このパッケージの開発過程で、サードパーティの読み込みに関する推奨事項を統合して、他のフレームワークでも同じ基盤技術を利用できるようにする必要があることがわかりました。このため、JSON を使用してサードパーティの読み込み手法を記述するライブラリである サードパーティ キャピタルを構築しました。これは現在、@next/third-parties の基盤として機能しています。

次のステップとして、Next.js 用に提供されているコンポーネントの改善に引き続き注力するとともに、他の一般的なフレームワークや CMS プラットフォームにも同様のユーティリティを追加する取り組みを拡大していきます。現在、Google は Nuxt のメンテナンス担当者と連携しており、近い将来、そのエコシステムに合わせて調整された同様のサードパーティ ユーティリティをリリースする予定です。

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