Nuxt パフォーマンス

Nuxt アプリのパフォーマンスを向上させるためのベストプラクティス。

Nuxt には、アプリケーションのパフォーマンスを向上させ、より良いCore Web Vitalsに貢献するように設計された組み込み機能が搭載されています。また、特定の領域でパフォーマンスを向上させるのに役立つ Nuxt コアモジュールも複数あります。このガイドでは、Nuxt アプリケーションのパフォーマンスを最適化するためのベストプラクティスについて説明します。

組み込み機能

Nuxt は、ウェブサイトのパフォーマンスを最適化するのに役立ついくつかの組み込み機能を提供しています。これらの機能がどのように機能するかを理解することは、非常に高速なパフォーマンスを実現するために不可欠です。

<NuxtLink> は、Vue Router の <RouterLink> コンポーネントと HTML の <a> タグの両方に対応するドロップイン代替品です。リンクが内部か外部かをインテリジェントに判断し、利用可能な最適化 (プリフェッチ、デフォルト属性など) を適用して適切にレンダリングします。

<template>
  <NuxtLink to="/about">About page</NuxtLink>
</template>

<!-- Which will render to with Vue Router & Smart Prefetching -->
<a href="/about">About page</a>

Nuxt はスマートなプリフェッチを自動的に含みます。つまり、リンクがビューポート内またはスクロール時に表示されていることを (デフォルトで) 検出し、ユーザーがリンクをクリックしたときにページがすぐに表示されるように、これらのページの JavaScript をプリフェッチします。

代わりに、インタラクション時のプリフェッチを選択することもできます。

export default defineNuxtConfig({
  experimental: {
    defaults: {
      nuxtLink: {
        prefetchOn: 'interaction',
      },
    },
  },
})
NuxtLink で詳細をご覧ください。

ハイブリッドレンダリング

より複雑なアプリケーションでは、一部のページをビルド時に生成し、他のページをクライアント側でレンダリングする必要がある場合に、アプリケーションのレンダリング方法を完全に制御する必要がある場合があります。

ハイブリッドレンダリングでは、ルートルールを使用してルートごとに異なるキャッシュルールを許可し、特定の URL への新しいリクエストに対してサーバーがどのように応答するかを決定します。

export default defineNuxtConfig({
  routeRules: {
    '/': {
      prerender: true,
    },
    '/products/**': {
      swr: 3600,
    },
    '/blog': {
      isr: 3600,
    },
    '/admin/**': {
      ssr: false,
    },
  },
})

Nuxt サーバーは、対応するミドルウェアを自動的に登録し、Nitro キャッシュ層を使用してキャッシュハンドラーでルートをラップします。

ハイブリッドレンダリングで詳細をご覧ください。

コンポーネントの遅延ロード

コンポーネントを動的にインポートする (コンポーネントを遅延ロードするとも呼ばれます) には、コンポーネント名に Lazy プレフィックスを追加するだけです。これは、コンポーネントが常に必要とされるわけではない場合に便利です。

<script setup lang="ts">
const show = ref(false)
</script>

<template>
  <div>
    <h1>Mountains</h1>
    <LazyMountainsList v-if="show" />
    <button v-if="!show" @click="show = true">Show List</button>
  </div>
</template>

Lazy プレフィックスを使用することで、適切なタイミングまでコンポーネントコードのロードを遅らせることができ、JavaScript バンドルサイズの最適化に役立ちます。

コンポーネントの遅延ロードで詳細をご覧ください。

遅延ハイドレーション

最初のロード時にサイトのすべてのコンポーネントをハイドレート (またはインタラクティブにする) する必要は必ずしもありません。遅延ハイドレーションを使用すると、コンポーネントのコードをロードするタイミングを制御でき、アプリのインタラクティブになるまでの時間を改善できます。Nuxt は、遅延ハイドレーション (Nuxt v3.16 で追加) を使用して、コンポーネントがインタラクティブになるタイミングを制御できます。

<template>
  <div>
    <LazyMyComponent hydrate-on-visible />
  </div>
</template>

アプリを最適化するには、一部のコンポーネントのハイドレーションを、表示されるまで、またはブラウザがより重要なタスクを完了するまで遅らせる必要がある場合があります。

遅延ハイドレーションで詳細をご覧ください。

データの取得

同じデータを2回 (サーバーで1回、クライアントで1回) フェッチするのを避けるために、Nuxt は useFetchuseAsyncData を提供しています。これらは、API 呼び出しがサーバーで行われた場合、データが再度フェッチされるのではなく、ペイロードとしてクライアントに転送されることを保証します。

データフェッチで詳細をご覧ください。

コア Nuxt モジュール

Nuxt の組み込み機能以外にも、Nuxt チームによってメンテナンスされているコアモジュールがあり、パフォーマンスをさらに向上させるのに役立ちます。これらのモジュールは、画像、カスタムフォント、サードパーティスクリプトなどのアセットの処理に役立ちます。

画像

最適化されていない画像は、ウェブサイトのパフォーマンス、特に最大視覚コンテンツの描画 (LCP)スコアに大きな悪影響を与える可能性があります。

Nuxt では、Nuxt ImageNuxt アプリ用のプラグアンドプレイ画像最適化モジュールを使用できます。組み込みのオプティマイザーまたはお気に入りの画像 CDN を使用して、画像のサイズ変更と変換が可能です。

<NuxtImg> は、以下の機能強化が施されたネイティブの <img> タグのドロップイン代替品です。

  • 組み込みプロバイダーを使用してローカルおよびリモート画像を最適化します。
  • src を WebP や Avif などのモダンな形式でプロバイダー最適化された URL に変換します。
  • widthheight に基づいて画像を自動的にサイズ変更します。
  • サイズオプションを指定すると、レスポンシブな sizes を生成します。
  • ネイティブの lazy loading およびその他の <img> 属性をサポートします。

ウェブサイトの画像は通常、重要度によって分類できます。最初の読み込み時に最初に配信する必要があるもの (つまり、最大視覚コンテンツの描画) と、後で、または特に必要なときに読み込むことができるものです。そのためには、次の最適化を使用できます。

<template>
  <!-- 🚨 Needs to be loaded ASAP -->
  <NuxtImg
    src="/hero-banner.jpg"
    format="webp"
    preload
    loading="eager"
    fetch-priority="high"
    width="200"
    height="100"
  />

  <!-- 🐌 Can be loaded later -->
  <NuxtImg
    src="/facebook-logo.jpg"
    format="webp"
    loading="lazy"
    fetch-priority="low"
    width="200"
    height="100"
  />
</template>
Nuxt Image で詳細をご覧ください。

フォント

Nuxt Fontsは、フォント (カスタムフォントを含む) を自動的に最適化し、プライバシーとパフォーマンスの向上のために外部ネットワークリクエストを削除します。

すべてのフォントファイルの組み込み自動自己ホスティングが含まれているため、基盤となるパッケージfontaine.

Nuxt Fonts の背後にあるアイデアについて、Daniel Roe の講演をご覧ください

  1. Nuxt Fonts は、すべての CSS を処理し、`font-family` 宣言に出くわすと、以下のことを自動的に行います。
  2. フォントの解決 – `public/` 内のフォントファイルを検索し、Google、Bunny、Fontshare などのウェブプロバイダーをチェックします。
  3. `@font-face` ルールの生成 – 正しいソースからフォントを読み込むための CSS ルールを挿入します。
  4. フォントのプロキシとキャッシュ – URL を /_fonts に書き換え、フォントをローカルにダウンロードしてキャッシュします。CLS).
  5. フォールバックメトリックの作成 – ウェブフォントと一致するようにローカルシステムフォントを調整し、レイアウトシフトを低減します。

ビルドへのフォントの組み込み – フォントをプロジェクトにバンドルし、ファイル名をハッシュ化し、長期間有効なキャッシュヘッダーを設定します。

複数のプロバイダーをサポートしており、プラグイン可能で拡張可能なように設計されているため、セットアップに関係なく、既存のプロバイダーを使用したり、独自のプロバイダーを作成したりできます。

スクリプト分析ツール、動画埋め込み、地図、ソーシャルメディア連携などのサードパーティリソースはウェブサイトの機能を強化しますが、ユーザーエクスペリエンスを著しく低下させ、次の描画へのインタラクション (INP)

Nuxt Scriptsと最大視覚コンテンツの描画 (LCP) のスコアに悪影響を与える可能性があります。

Alex Lichter の Nuxt Scripts に関するビデオをご覧ください

const { onLoaded, proxy } = useScriptGoogleAnalytics(
  {
    id: 'G-1234567',
    scriptOptions: {
      trigger: 'manual',
    },
  },
)
// queue events to be sent when ga loads
proxy.gtag('config', 'UA-123456789-1')
// or wait until ga is loaded
onLoaded((gtag) => {
  // script loaded
})
Nuxt Scripts は、サードパーティスクリプトの上に抽象化レイヤーを提供し、SSR サポートと型安全性を提供しながら、スクリプトのロード方法を完全に低レベルで制御できます。

Nuxt Scripts で詳細をご覧ください。

プロファイリングツール

パフォーマンスを向上させるには、まずその測定方法を知る必要があります。まず、開発中のローカル環境でパフォーマンスを測定し、次に本番環境にデプロイされたアプリケーションを監査します。

Nuxi Analyze

nuxiこの コマンドは、Nuxt アプリケーションのプロダクションバンドルを分析することを可能にします。vite-bundle-visualizer ( webpack-bundle-analyzer に似ています) を利用して、アプリケーションのバンドルの視覚的な表現を生成し、どのコンポーネントが最もスペースを占めているかを簡単に特定できるようにします。

視覚化で大きなブロックが表示された場合、それは最適化の機会を示していることがよくあります。特にサードパーティライブラリの場合、それをより小さなパーツに分割したり、遅延ロードを実装したり、より効率的な代替品に置き換えたりすることが考えられます。

Nuxt DevTools

が悪化します。Nuxt DevTools複数の要素を含む大きなブロックは、モジュール全体ではなく必要なコンポーネントのみをインポートすることで削減できることがよくあります。一方、大きなスタンドアロンブロックは、メインバンドルに含めるよりも遅延ロードに適している場合があります。

は、Nuxt アプリに関する洞察と透過性を提供し、パフォーマンスのギャップを特定し、アプリの構成をシームレスに管理できます。

  1. Nuxt アプリのパフォーマンスを測定するために使用できるいくつかの機能が付属しています。
  2. タイムライン – レンダリング、更新、コンポーネントの初期化に費やされた時間を追跡し、パフォーマンスのボトルネックを特定します。
  3. アセット – 変換なしでファイルサイズ (例: 画像) を表示します。
  4. レンダーツリー – Vue コンポーネント、スクリプト、スタイルの間の接続を示し、動的なロードを最適化します。

インスペクト – Vue アプリで使用されているすべてのファイルを、そのサイズと評価時間とともにリスト表示します。

Chrome DevTools

Chrome DevTools には、パフォーマンス測定に役立つ2つのタブがあります。PerformanceLighthouse です。パフォーマンスPerformance パネルを開くと、ローカルの 最大視覚コンテンツの描画 (LCP)累積レイアウトシフト (CLS) スコア (良好、改善が必要、または不良) がすぐに表示されます。

ページを操作すると、次の描画へのインタラクション (INP) もキャプチャされ、デバイスとネットワークに基づいた Core Web Vitals の完全なビューが得られます。

Lighthouseは、パフォーマンス、アクセシビリティ、SEO、プログレッシブウェブアプリ、およびベストプラクティスを監査します。ページでテストを実行し、レポートを生成します。失敗した監査をサイト改善のガイドとして使用してください。

各監査には、その監査がなぜ重要なのか、そしてそれを修正する方法を説明する参考ドキュメントがあります。

PageSpeed Insights

PageSpeed Insights (PSI)は、モバイルデバイスとデスクトップデバイスの両方でのページのユーザーエクスペリエンスを報告し、そのページを改善する方法に関する提案を提供します。

ページに関するラボデータとフィールドデータの両方を提供します。ラボデータは、制御された環境で収集されるため、問題のデバッグに役立ちます。一方、フィールドデータは、真の現実世界のユーザーエクスペリエンスをキャプチャするのに役立ちます。

Web Page Test

WebPageTestは、さまざまな条件下でページがどのように動作するかに関する詳細な診断情報を提供するウェブパフォーマンスツールです。

各テストは、世界中のさまざまな場所から、実際のブラウザで、任意の数のカスタマイズ可能なネットワーク条件で実行できます。

一般的な問題

より複雑な Nuxt アプリケーションを構築する場合、おそらく以下に示す問題のいくつかに出くわすでしょう。これらの問題を理解し、修正することで、ウェブサイトのパフォーマンスを向上させるのに役立ちます。

プラグインの過剰な使用

問題: 多数のプラグインは、特に高価な計算を必要としたり、初期化に時間がかかりすぎたりする場合、パフォーマンスの問題を引き起こす可能性があります。プラグインはハイドレーションフェーズ中に実行されるため、非効率なセットアップはレンダリングをブロックし、ユーザーエクスペリエンスを低下させる可能性があります。

解決策: プラグインを調べ、それらの一部がコンポーザブルまたはユーティリティ関数として実装できるかどうかを確認します。

未使用のコード/依存関係

問題: プロジェクトの開発が進むにつれて、未使用のコードや依存関係が発生する場合があります。この追加機能は使用または必要とされていないにもかかわらず、プロジェクトのバンドルサイズを増加させます。

解決策: package.json を調べて未使用の依存関係がないか確認し、コードを分析して未使用のユーティリティ/コンポーザブル/関数がないか確認します。

Vue のパフォーマンスのヒントを使用しない

問題: Vue のドキュメントには、Nuxt プロジェクトでも使用できるいくつかのパフォーマンス改善がリストされていますが、それらは Vue ドキュメントの一部であるため、開発者はそれらを忘れがちで、Nuxt 特有の改善のみに焦点を当ててしまいます。しかし、Nuxt アプリケーションは依然として Vue プロジェクトです。

解決策: shallowRefv-memov-once などの概念を使用してパフォーマンスを向上させます。

パターンに従わない

問題: 現在プロジェクトに多くの人が関わっているほど、安定したコードベースを維持するのが難しくなります。開発者は、他のプロジェクトで見た新しい概念を導入する傾向があり、それがパフォーマンスの競合や問題を引き起こす可能性があります。

解決策: プロジェクト内で、次のようなルールとパターンを確立します。Vue Composables の良い習慣とデザインパターン

すべてを同時に読み込もうとする

問題: ページが読み込まれる際に、要素の読み込み順序が正しく指示されていない場合、すべてが同時にフェッチされることになります。これは遅くなり、ユーザーエクスペリエンスの低下につながります。

解決策: プログレッシブエンハンスメントなどの概念を使用します。これにより、まずコアのウェブページコンテンツが設定され、その後、ブラウザ/インターネット接続が許す範囲で、より繊細で技術的に厳密なプレゼンテーションと機能のレイヤーが追加されます。

役立つリソース

パフォーマンスを向上させるためのさまざまなテクニックについて詳しく学ぶには、以下のリソースを参照してください。

  1. PRPL パターンで即時ロードを適用する
  2. 知覚されるパフォーマンス
  3. クリティカルレンダリングパスを理解する