レンダリングモード
Nuxtで利用可能なさまざまなレンダリングモードについて学びましょう。
Nuxtは、ユニバーサルレンダリング、クライアントサイドレンダリングをサポートしていますが、ハイブリッドレンダリングやCDNエッジサーバーでのアプリケーションのレンダリングも可能です。
ブラウザとサーバーの両方がJavaScriptコードを解釈してVue.jsコンポーネントをHTML要素に変換できます。このステップはレンダリングと呼ばれます。Nuxtはユニバーサルとクライアントサイドの両方のレンダリングをサポートしています。これらのアプローチには利点と欠点があり、それについて説明します。
デフォルトでは、Nuxtはユニバーサルレンダリングを使用して、より良いユーザーエクスペリエンス、パフォーマンス、検索エンジンのインデックス最適化を提供しますが、1行の設定でレンダリングモードを切り替えることができます。
ユニバーサルレンダリング
このステップは、PHPやRubyアプリケーションによって実行される従来のサーバーサイドレンダリングに似ています。ブラウザがユニバーサルレンダリングが有効なURLを要求すると、Nuxtはサーバー環境でJavaScript(Vue.js)コードを実行し、完全にレンダリングされたHTMLページをブラウザに返します。Nuxtは、ページが事前に生成されている場合、キャッシュから完全にレンダリングされたHTMLページを返すこともあります。クライアントサイドレンダリングとは異なり、ユーザーはアプリケーションの初期コンテンツ全体を即座に取得します。
HTMLドキュメントがダウンロードされると、ブラウザはこれを解釈し、Vue.jsがドキュメントを制御します。サーバーで一度実行された同じJavaScriptコードが、クライアント(ブラウザ)で再びバックグラウンドで実行され、リスナーをHTMLにバインドすることでインタラクティビティを可能にします(これがユニバーサルレンダリングです)。これをハイドレーションと呼びます。ハイドレーションが完了すると、ページは動的なインターフェースやページ遷移などの利点を享受できます。
ユニバーサルレンダリングにより、Nuxtアプリケーションはクライアントサイドレンダリングの利点を維持しながら、迅速なページロード時間を提供できます。さらに、コンテンツがすでにHTMLドキュメントに存在するため、クローラーはオーバーヘッドなしでインデックスを作成できます。
サーバーでレンダリングされるものとクライアントでレンダリングされるものは何ですか?
ユニバーサルレンダリングモードで、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はコードがどこで実行されるかを判断するためのガイドラインと特定の変数を提供しています。
- コスト: ページを動的にレンダリングするためにはサーバーが稼働している必要があります。これは従来のサーバーと同様に月額コストがかかります。ただし、ユニバーサルレンダリングにより、クライアントサイドのナビゲーションでブラウザが引き継ぐため、サーバーコールは大幅に削減されます。エッジサイドレンダリングを活用することでコスト削減が可能です。
ユニバーサルレンダリングは非常に柔軟で、ほぼすべてのユースケースに適合し、特にコンテンツ指向のウェブサイトに適しています:ブログ、マーケティングウェブサイト、ポートフォリオ、eコマースサイト、マーケットプレイス。
ハイドレーションの不一致なしにVueコードを書くためのさらなる例については、Vueのドキュメントを参照してください。
ブラウザAPIに依存し副作用のあるライブラリをインポートする場合、それをインポートするコンポーネントがクライアントサイドでのみ呼び出されるようにしてください。バンドラーは副作用を含むモジュールのインポートをツリーシェイクしません。
クライアントサイドレンダリング
標準のVue.jsアプリケーションは、ブラウザ(またはクライアント)でレンダリングされます。その後、Vue.jsは、現在のインターフェースを作成するための指示を含むすべてのJavaScriptコードをブラウザがダウンロードして解析した後にHTML要素を生成します。
クライアントサイドレンダリングの利点:
- 開発速度: 完全にクライアントサイドで作業する場合、コードのサーバー互換性を心配する必要がありません。たとえば、
window
オブジェクトのようなブラウザ専用のAPIを使用する場合です。 - 安価: サーバーを稼働させると、JavaScriptをサポートするプラットフォームで実行する必要があるため、インフラストラクチャのコストがかかります。クライアント専用のアプリケーションは、HTML、CSS、JavaScriptファイルを持つ任意の静的サーバーでホストできます。
- オフライン: コードが完全にブラウザで実行されるため、インターネットが利用できない場合でも正常に動作し続けることができます。
クライアントサイドレンダリングの欠点:
- パフォーマンス: ユーザーは、ブラウザがJavaScriptファイルをダウンロード、解析、実行するのを待たなければなりません。ダウンロード部分はネットワークに依存し、解析と実行はユーザーのデバイスに依存するため、時間がかかり、ユーザーエクスペリエンスに影響を与える可能性があります。
- 検索エンジン最適化: クライアントサイドレンダリングで提供されるコンテンツのインデックス作成と更新には、サーバーレンダリングされたHTMLドキュメントよりも時間がかかります。これは、パフォーマンスの欠点に関連しており、検索エンジンクローラーは、インターフェースが完全にレンダリングされるのを待たずにページをインデックス化しようとします。純粋なクライアントサイドレンダリングでは、コンテンツが検索結果ページに表示され、更新されるまでに時間がかかります。
クライアントサイドレンダリングは、インデックス作成が不要またはユーザーが頻繁に訪れるインタラクティブなWebアプリケーションに適した選択です。ブラウザキャッシュを活用して、次回の訪問時にダウンロードフェーズをスキップできます。たとえば、SaaS、バックオフィスアプリケーション、オンラインゲームなどです。
Nuxtでクライアントサイドのみのレンダリングを有効にするには、nuxt.config.ts
で次のように設定します:
export default defineNuxtConfig({
ssr: false
})
ssr: false
を使用する場合、アプリがハイドレートされるまでレンダリングされるローディング画面を表示するために、~/app/spa-loading-template.html
にHTMLファイルを配置する必要があります。
静的クライアントレンダリングアプリのデプロイ
nuxt generate
またはnuxt build --prerender
コマンドを使用して静的ホスティングにアプリをデプロイする場合、デフォルトでNuxtは各ページを個別の静的HTMLファイルとしてレンダリングします。
nuxt generate
またはnuxt build --prerender
コマンドでアプリをプリレンダリングする場合、出力フォルダにサーバーが含まれないため、サーバーエンドポイントを使用することはできません。サーバー機能が必要な場合は、nuxt build
を使用してください。
純粋にクライアントサイドレンダリングを使用している場合、これは不要かもしれません。単一のindex.html
ファイルと、200.html
および404.html
のフォールバックだけが必要かもしれません。これらを静的Webホストにすべてのリクエストに対して提供するように指示できます。
これを実現するために、ルートのプリレンダリング方法を変更できます。nuxt.config.ts
のフックに次のように追加します:
export default defineNuxtConfig({
hooks: {
'prerender:routes' ({ routes }) {
routes.clear() // ルートを生成しない(デフォルトを除く)
}
},
})
これにより、次の3つのファイルが生成されます:
index.html
200.html
404.html
200.html
と404.html
は、使用しているホスティングプロバイダーに役立つかもしれません。
クライアントフォールバック生成のスキップ
クライアントレンダリングアプリをプリレンダリングする際、Nuxtはデフォルトでindex.html
、200.html
、404.html
ファイルを生成します。ただし、ビルドでこれらのファイルの生成を防ぐ必要がある場合、Nitroの'prerender:generate'
フックを使用できます。
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アプリケーションとサーバーのすべてのルート/ページが同じレンダリングモード(ユニバーサルまたはクライアントサイド)を使用する必要がありました。さまざまなケースで、一部のページはビルド時に生成されるべきであり、他のページはクライアントサイドでレンダリングされるべきです。たとえば、管理セクションを持つコンテンツウェブサイトを考えてみてください。すべてのコンテンツページは主に静的で一度生成されるべきですが、管理セクションは登録が必要で、より動的なアプリケーションのように振る舞います。
Nuxtにはルートルールとハイブリッドレンダリングのサポートが含まれています。ルートルールを使用して、Nuxtルートのグループに対してルールを定義し、レンダリングモードを変更したり、ルートに基づいてキャッシュ戦略を割り当てたりできます!
Nuxtサーバーは自動的に対応するミドルウェアを登録し、Nitroキャッシングレイヤーを使用してキャッシュハンドラーでルートをラップします。
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
- サーバーサイドリダイレクトを定義します。ssr: boolean
- アプリのセクションのサーバーサイドレンダリングを無効にし、ssr: false
でブラウザでのみレンダリングします。cors: boolean
-cors: true
で自動的にCORSヘッダーを追加します -headers
で出力をカスタマイズできます。headers: object
- サイトの特定のセクションに特定のヘッダーを追加します - たとえば、アセットに。swr: number | boolean
- サーバーレスポンスにキャッシュヘッダーを追加し、サーバーまたはリバースプロキシで設定可能なTTL(有効期限)でキャッシュします。Nitroのnode-server
プリセットは、完全なレスポンスをキャッシュできます。TTLが切れると、キャッシュされたレスポンスが送信され、ページはバックグラウンドで再生成されます。true
が使用される場合、stale-while-revalidate
ヘッダーがMaxAgeなしで追加されます。isr: number | boolean
- 振る舞いはswr
と同じですが、これにより、対応するプラットフォーム(現在はNetlifyまたはVercel)でCDNキャッシュにレスポンスを追加できます。true
が使用される場合、コンテンツは次のデプロイまでCDN内に保持されます。prerender: boolean
- ビルド時にルートをプリレンダリングし、静的アセットとしてビルドに含めます。noScripts: boolean
- サイトのセクションに対するNuxtスクリプトとJSリソースヒントのレンダリングを無効にします。appMiddleware: string | string[] | Record<string, boolean>
- アプリケーションの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
環境変数を使用
ハイブリッドレンダリングは、ルートルールを使用したエッジサイドレンダリングと組み合わせて使用することができます。
上記のプラットフォームのいくつかにデプロイされたオープンソースの例を探索できます:
※このページは Nuxt.js 公式ドキュメントの翻訳ページ(非公式)です。
公式ドキュメントの該当ページはこちら:
https://nuxt.com/docs/3.x/guide/concepts/rendering