nuxt logo

ドキュメント翻訳(非公式)

レンダリングモード

Nuxtで利用可能なさまざまなレンダリングモードについて学びましょう。

Nuxtは、ユニバーサルレンダリングクライアントサイドレンダリングをサポートしていますが、ハイブリッドレンダリングやアプリケーションをCDNエッジサーバーでレンダリングする可能性も提供しています。

ブラウザとサーバーの両方がJavaScriptコードを解釈してVue.jsコンポーネントをHTML要素に変換できます。このステップはレンダリングと呼ばれます。Nuxtはユニバーサルおよびクライアントサイドレンダリングの両方をサポートしています。この2つのアプローチには利点と欠点があり、それについて説明します。

デフォルトでは、Nuxtはユニバーサルレンダリングを使用して、より良いユーザーエクスペリエンス、パフォーマンスを提供し、検索エンジンのインデックス作成を最適化しますが、1行の設定でレンダリングモードを切り替えることができます。

ユニバーサルレンダリング

このステップは、PHPやRubyアプリケーションによって実行される従来のサーバーサイドレンダリングに似ています。ブラウザがユニバーサルレンダリングが有効なURLを要求すると、Nuxtはサーバー環境でJavaScript(Vue.js)コードを実行し、完全にレンダリングされたHTMLページをブラウザに返します。Nuxtは、ページが事前に生成されている場合、キャッシュから完全にレンダリングされたHTMLページを返すこともあります。クライアントサイドレンダリングとは異なり、ユーザーはアプリケーションの初期コンテンツ全体をすぐに取得します。

HTMLドキュメントがダウンロードされると、ブラウザはこれを解釈し、Vue.jsがドキュメントを制御します。サーバーで一度実行された同じJavaScriptコードが、今度はクライアント(ブラウザ)で再びバックグラウンドで実行され、リスナーをHTMLにバインドすることでインタラクティビティを可能にします(したがってユニバーサルレンダリング)。これをハイドレーションと呼びます。ハイドレーションが完了すると、ページは動的なインターフェースやページ遷移などの利点を享受できます。

ユニバーサルレンダリングにより、Nuxtアプリケーションはクライアントサイドレンダリングの利点を維持しながら、迅速なページロード時間を提供できます。さらに、コンテンツがすでにHTMLドキュメントに存在するため、クローラーはオーバーヘッドなしでインデックスを作成できます。

HTMLドキュメントが読み込まれると、ユーザーは静的コンテンツにアクセスできます。ハイドレーションによりページのインタラクティビティが可能になります

サーバーでレンダリングされるものとクライアントでレンダリングされるものは何ですか?

ユニバーサルレンダリングモードで、Vueファイルのどの部分がサーバーおよび/またはクライアントで実行されるのかを尋ねるのは普通のことです。

app/app.vue
<script setup lang="ts">
const counter = ref(0); // サーバーとクライアント環境で実行されます

const handleClick = () => {
  counter.value++; // クライアント環境でのみ実行されます
};
</script>

<template>
  <div>
    <p>Count: {{ counter }}</p>
    <button @click="handleClick">Increment</button>
  </div>
</template>

初回リクエスト時、counter refはサーバーで初期化されます。これは<p>タグ内でレンダリングされるためです。handleClickの内容はここでは実行されません。ブラウザでのハイドレーション中に、counter refは再初期化されます。handleClickは最終的にボタンにバインドされます。したがって、handleClickの本体は常にブラウザ環境で実行されると推測するのが合理的です。

ミドルウェアページは、ハイドレーション中にサーバーとクライアントの両方で実行されます。プラグインはサーバーまたはクライアント、またはその両方でレンダリングできます。コンポーネントはクライアントのみで実行されるように強制することもできます。コンポーザブルユーティリティは、その使用コンテキストに基づいてレンダリングされます。

サーバーサイドレンダリングの利点:

  • パフォーマンス: ユーザーはページのコンテンツに即座にアクセスできます。ブラウザは静的コンテンツをJavaScript生成コンテンツよりもはるかに速く表示できるためです。同時に、Nuxtはハイドレーションプロセス中にWebアプリケーションのインタラクティビティを維持します。
  • 検索エンジン最適化: ユニバーサルレンダリングは、ページのHTMLコンテンツ全体をクラシックなサーバーアプリケーションとしてブラウザに提供します。Webクローラーはページのコンテンツを直接インデックス化できるため、ユニバーサルレンダリングは迅速にインデックス化したいコンテンツに最適です。

サーバーサイドレンダリングの欠点:

  • 開発の制約: サーバーとブラウザの環境は同じAPIを提供しないため、両方の側でシームレスに実行できるコードを書くのは難しい場合があります。幸いなことに、Nuxtはコードがどこで実行されるかを判断するためのガイドラインと特定の変数を提供しています。
  • コスト: ページを動的にレンダリングするためにはサーバーを稼働させる必要があります。これは従来のサーバーと同様に月額コストがかかります。ただし、ユニバーサルレンダリングにより、クライアントサイドのナビゲーションでブラウザが引き継ぐため、サーバーコールは大幅に削減されます。エッジサイドレンダリングを活用することでコスト削減が可能です。

ユニバーサルレンダリングは非常に柔軟で、ほぼすべてのユースケースに適合し、特にコンテンツ指向のWebサイトに適しています:ブログ、マーケティングサイト、ポートフォリオ、eコマースサイト、マーケットプレイス

ハイドレーションの不一致を避けてVueコードを書くための詳細な例については、Vueのドキュメントを参照してください。

ブラウザAPIに依存し副作用を持つライブラリをインポートする場合、そのライブラリをインポートするコンポーネントがクライアントサイドでのみ呼び出されるようにしてください。バンドラーは副作用を含むモジュールのインポートをツリーシェイクしません。

クライアントサイドレンダリング

標準のVue.jsアプリケーションは、ブラウザ(またはクライアント)でレンダリングされます。その後、Vue.jsは、現在のインターフェースを作成するための指示を含むすべてのJavaScriptコードをブラウザがダウンロードして解析した後にHTML要素を生成します。

ユーザーはブラウザがJavaScriptをダウンロード、解析、実行するのを待たなければなりません

クライアントサイドレンダリングの利点:

  • 開発速度: 完全にクライアントサイドで作業する場合、コードのサーバー互換性を心配する必要がありません。例えば、windowオブジェクトのようなブラウザ専用のAPIを使用することができます。
  • 安価: サーバーを稼働させると、JavaScriptをサポートするプラットフォームで実行する必要があるため、インフラストラクチャのコストがかかります。クライアント専用のアプリケーションは、HTML、CSS、JavaScriptファイルを持つ任意の静的サーバーでホストできます。
  • オフライン: コードが完全にブラウザで実行されるため、インターネットが利用できない場合でもうまく動作し続けることができます。

クライアントサイドレンダリングの欠点:

  • パフォーマンス: ユーザーはブラウザがJavaScriptファイルをダウンロード、解析、実行するのを待たなければなりません。ダウンロード部分はネットワークに依存し、解析と実行はユーザーのデバイスに依存するため、時間がかかり、ユーザーエクスペリエンスに影響を与える可能性があります。
  • 検索エンジン最適化: クライアントサイドレンダリングで提供されるコンテンツのインデックス作成と更新には、サーバーレンダリングされたHTMLドキュメントよりも時間がかかります。これは、パフォーマンスの欠点に関連しており、検索エンジンクローラーは最初の試みでインターフェースが完全にレンダリングされるのを待たないためです。純粋なクライアントサイドレンダリングでは、コンテンツが検索結果ページに表示され、更新されるまでに時間がかかります。

クライアントサイドレンダリングは、インデックス作成が不要で、ユーザーが頻繁に訪れるインタラクティブなWebアプリケーションに適しています。ブラウザキャッシュを活用して、再訪時にダウンロードフェーズをスキップすることができます。例えば、SaaS、バックオフィスアプリケーション、オンラインゲームなどです。

Nuxtでクライアントサイドのみのレンダリングを有効にするには、nuxt.config.tsで次のように設定します:

nuxt.config.ts
export default defineNuxtConfig({
  ssr: false
})

ssr: falseを使用する場合、~/spa-loading-template.htmlにHTMLファイルを配置し、アプリがハイドレートされるまでレンダリングされるローディング画面をレンダリングするためのHTMLを使用する必要があります。

こちらも参照 SPA Loading Template

静的クライアントレンダリングアプリのデプロイ

アプリをnuxt generateまたはnuxt build --prerenderコマンドで静的ホスティングにデプロイする場合、デフォルトでNuxtは各ページを個別の静的HTMLファイルとしてレンダリングします。

nuxt generateまたはnuxt build --prerenderコマンドでアプリをプリレンダリングする場合、出力フォルダにサーバーが含まれないため、サーバーエンドポイントを使用することはできません。サーバー機能が必要な場合は、nuxt buildを使用してください。

純粋にクライアントサイドレンダリングを使用している場合、これは不要かもしれません。単一のindex.htmlファイルと、200.htmlおよび404.htmlのフォールバックだけが必要かもしれません。これらを静的Webホストにすべてのリクエストに対して提供するように指示できます。

これを達成するために、ルートのプリレンダリング方法を変更できます。nuxt.config.tsフックに次のように追加します:

nuxt.config.ts
export default defineNuxtConfig({
  hooks: {
    'prerender:routes' ({ routes }) {
      routes.clear() // ルートを生成しない(デフォルトを除く)
    }
  },
})

これにより、次の3つのファイルが生成されます:

  • index.html
  • 200.html
  • 404.html

200.html404.htmlは、使用しているホスティングプロバイダーに役立つかもしれません。

クライアントフォールバック生成のスキップ

クライアントレンダリングアプリをプリレンダリングする際、Nuxtはデフォルトでindex.html200.html404.htmlファイルを生成します。ただし、ビルドでこれらのファイルのいずれか(またはすべて)の生成を防ぐ必要がある場合は、Nitro'prerender:generate'フックを使用できます。

nuxt.config.ts
export default defineNuxtConfig({
  ssr: false,
  nitro: {
    hooks: {
      'prerender:generate'(route) {
        const routesToSkip = ['/index.html', '/200.html', '/404.html']
        if (routesToSkip.includes(route.route)) {
          route.skip = true
        }
      }
    }
  }
})

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

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

以前は、Nuxtアプリケーションとサーバーのすべてのルート/ページが同じレンダリングモード(ユニバーサルまたはクライアントサイド)を使用する必要がありました。さまざまなケースで、一部のページはビルド時に生成され、他のページはクライアントサイドでレンダリングされるべきです。例えば、管理セクションを持つコンテンツWebサイトを考えてみてください。すべてのコンテンツページは主に静的で一度生成されるべきですが、管理セクションは登録が必要で、より動的なアプリケーションのように振る舞います。

Nuxtはルートルールとハイブリッドレンダリングのサポートを含んでいます。ルートルールを使用して、Nuxtルートのグループに対してルールを定義し、レンダリングモードを変更したり、ルートに基づいてキャッシュ戦略を割り当てたりできます!

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

nuxt.config.ts
export default defineNuxtConfig({
  routeRules: {
    // ホームページはビルド時にプリレンダリングされます
    '/': { prerender: true },
    // 製品ページはオンデマンドで生成され、バックグラウンドで再検証され、APIレスポンスが変更されるまでキャッシュされます
    '/products': { swr: true },
    // 製品ページはオンデマンドで生成され、バックグラウンドで再検証され、1時間(3600秒)キャッシュされます
    '/products/**': { swr: 3600 },
    // ブログ投稿ページはオンデマンドで生成され、バックグラウンドで再検証され、CDNで1時間(3600秒)キャッシュされます
    '/blog': { isr: 3600 },
    // ブログ投稿ページは次のデプロイまでオンデマンドで一度生成され、CDNでキャッシュされます
    '/blog/**': { isr: true },
    // 管理ダッシュボードはクライアントサイドでのみレンダリングされます
    '/admin/**': { ssr: false },
    // APIルートにcorsヘッダーを追加します
    '/api/**': { cors: true },
    // レガシーURLをリダイレクトします
    '/old-page': { redirect: '/new-page' }
  }
})

ルートルール

使用できるさまざまなプロパティは次のとおりです:

  • redirect: string{lang=ts} - サーバーサイドリダイレクトを定義します。
  • ssr: boolean{lang=ts} - アプリのセクションのHTMLのサーバーサイドレンダリングを無効にし、ssr: falseでブラウザでのみレンダリングします。
  • cors: boolean{lang=ts} - cors: trueで自動的にcorsヘッダーを追加します - headersで出力をカスタマイズできます。
  • headers: object{lang=ts} - サイトの特定のセクションに特定のヘッダーを追加します - 例えば、アセットに。
  • swr: number | boolean{lang=ts} - サーバーレスポンスにキャッシュヘッダーを追加し、サーバーまたはリバースプロキシで設定可能なTTL(存続時間)でキャッシュします。Nitroのnode-serverプリセットは、完全なレスポンスをキャッシュできます。TTLが切れると、キャッシュされたレスポンスが送信され、ページはバックグラウンドで再生成されます。trueが使用される場合、stale-while-revalidateヘッダーがMaxAgeなしで追加されます。
  • isr: number | boolean{lang=ts} - swrと同じ動作ですが、対応するプラットフォーム(現在はNetlifyまたはVercel)でCDNキャッシュにレスポンスを追加できます。trueが使用される場合、コンテンツは次のデプロイまでCDN内で保持されます。
  • prerender: boolean{lang=ts} - ビルド時にルートをプリレンダリングし、静的アセットとしてビルドに含めます。
  • noScripts: boolean{lang=ts} - サイトのセクションに対するNuxtスクリプトとJSリソースヒントのレンダリングを無効にします。
  • appMiddleware: string | string[] | Record<string, boolean>{lang=ts} - アプリケーションのVueアプリ部分内のページパスに対して実行するかしないかを定義するミドルウェアを許可します(つまり、Nitroルートではありません)。

可能な限り、ルートルールはデプロイメントプラットフォームのネイティブルールに自動的に適用され、最適なパフォーマンスを実現します(現在、NetlifyとVercelがサポートされています)。

ハイブリッドレンダリングはnuxt generateを使用する場合には利用できません。

例:

エッジサイドレンダリング

エッジサイドレンダリング(ESR)は、Nuxtに導入された強力な機能で、コンテンツデリバリネットワーク(CDN)のエッジサーバーを介してNuxtアプリケーションをユーザーに近づけてレンダリングすることができます。ESRを活用することで、パフォーマンスが向上し、レイテンシが低減され、ユーザーエクスペリエンスが向上します。

ESRでは、レンダリングプロセスがネットワークの「エッジ」、つまりCDNのエッジサーバーにプッシュされます。ESRは実際のレンダリングモードというよりもデプロイメントターゲットです。

ページのリクエストが行われると、元のサーバーに行く代わりに、最も近いエッジサーバーによってインターセプトされます。このサーバーがページのHTMLを生成し、ユーザーに返します。このプロセスにより、データが移動する物理的な距離が最小化され、レイテンシが低減され、ページがより速く読み込まれます

エッジサイドレンダリングは、Nuxtを支えるサーバーエンジンであるNitroのおかげで可能です。Node.js、Deno、Cloudflare Workersなど、クロスプラットフォームのサポートを提供します。

現在、ESRを活用できるプラットフォームは次のとおりです:

  • Cloudflare Pagesは、git統合とnuxt buildコマンドを使用してゼロ構成で利用可能
  • Vercel Edge Functionsは、nuxt buildコマンドとNITRO_PRESET=vercel-edge環境変数を使用
  • Netlify Edge Functionsは、nuxt buildコマンドとNITRO_PRESET=netlify-edge環境変数を使用

ハイブリッドレンダリングは、ルートルールを使用してエッジサイドレンダリングを使用する場合に利用できます。

上記のプラットフォームのいくつかにデプロイされたオープンソースの例を探索できます: