レンダリングモード
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ドキュメントに存在するため、クローラーはオーバーヘッドなしでインデックスを作成できます。
サーバーレンダリングとクライアントレンダリング
ユニバーサルレンダリングモードで、Vueファイルのどの部分がサーバーおよび/またはクライアントで実行されるか質問するのは当然です。
<script setup lang="ts">
const counter = ref(0); // executes in server and client environments
const handleClick = () => {
counter.value++; // executes only in a client environment
};
</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サイト、**ブログ、マーケティングWebサイト、ポートフォリオ、eコマースサイト、およびマーケットプレイス**に最適です。
クライアントサイドレンダリング
すぐに使える従来のVue.jsアプリケーションは、ブラウザ(または**クライアント**)でレンダリングされます。次に、Vue.jsは、ブラウザが現在のインターフェイスを作成する手順を含むすべてのJavaScriptコードをダウンロードして解析した後、HTML要素を生成します。
クライアントサイドレンダリングの利点
- 開発速度:クライアント側のみで作業する場合、たとえば、
window
オブジェクトなどのブラウザ専用のAPIを使用することで、コードのサーバー互換性を心配する必要はありません。 - 安価:サーバーを実行すると、JavaScriptをサポートするプラットフォームで実行する必要があるため、インフラストラクチャのコストが増加します。クライアントのみのアプリケーションは、HTML、CSS、およびJavaScriptファイルを使用して、任意の静的サーバーでホストできます。
- オフライン:コードはすべてブラウザで実行されるため、インターネットが利用できない場合でも正常に動作し続けることができます。
クライアントサイドレンダリングの欠点
- パフォーマンス:ユーザーは、ブラウザがJavaScriptファイルをダウンロード、解析、実行するのを待つ必要があります。ダウンロード部分のネットワークと、解析と実行を行うユーザーのデバイスによっては、時間がかかり、ユーザーエクスペリエンスに影響を与える可能性があります。
- 検索エンジン最適化:クライアントサイドレンダリングを介して配信されるコンテンツのインデックス作成と更新には、サーバーレンダリングされたHTMLドキュメントよりも時間がかかります。これは、検索エンジンのクローラーが、ページにインデックスを付けるために最初に完全にレンダリングされるのを待たないため、先に説明したパフォーマンスの欠点に関連しています。コンテンツが、純粋なクライアントサイドレンダリングで検索結果ページに表示および更新されるのに時間がかかります。
クライアントサイドレンダリングは、インデックス作成を必要としない、またはユーザーが頻繁に訪問する、インタラクティブ性の高い**Webアプリケーション**に最適です。**SaaS、バックオフィスアプリケーション、またはオンラインゲーム**など、後続の訪問時にダウンロードフェーズをスキップするためにブラウザキャッシュを活用できます。
nuxt.config.ts
でNuxtを使用したクライアントサイドのみのレンダリングを有効にできます。
export default defineNuxtConfig({
ssr: false
})
ssr: false
を使用する場合、アプリがハイドレートされるまで表示されるローディング画面をレンダリングするために使用するHTMLファイルを ~/app/spa-loading-template.html
に配置する必要があります。静的なクライアントレンダリングアプリのデプロイ
nuxi generate
または nuxi build --prerender
コマンドを使用して、アプリを静的ホスティングにデプロイする場合、Nuxtはデフォルトで各ページを個別の静的HTMLファイルとしてレンダリングします。
完全にクライアントサイドレンダリングを使用している場合、これは不要かもしれません。必要なのは、単一の index.html
ファイルと、すべてのリクエストに対して静的Webホストに提供させる 200.html
および 404.html
のフォールバックのみかもしれません。
これを実現するために、ルートのプリレンダリング方法を変更できます。nuxt.config.ts
のフックにこれを追加するだけです。
export default defineNuxtConfig({
hooks: {
'prerender:routes' ({ routes }) {
routes.clear() // Do not generate any routes (except the defaults)
}
},
})
これにより、3つのファイルが生成されます。
index.html
200.html
404.html
200.html
および 404.html
は、使用しているホスティングプロバイダーに役立つ場合があります。
ハイブリッドレンダリング
ハイブリッドレンダリングでは、ルートルールを使用してルートごとに異なるキャッシングルールを適用し、指定されたURLへの新しいリクエストに対してサーバーがどのように応答するかを決定します。
以前は、Nuxtアプリケーションとサーバーのすべてのルート/ページで、ユニバーサルまたはクライアントサイドの同じレンダリングモードを使用する必要がありました。さまざまなケースで、一部のページはビルド時に生成でき、他のページはクライアントサイドでレンダリングする必要があります。たとえば、管理者セクションがあるコンテンツWebサイトを考えてみてください。すべてのコンテンツページは、主に静的であり、一度生成されるべきですが、管理者セクションは登録を必要とし、より動的なアプリケーションのように動作します。
Nuxtには、ルートルールとハイブリッドレンダリングのサポートが含まれています。ルートルールを使用すると、Nuxtルートのグループのルールを定義したり、レンダリングモードを変更したり、ルートに基づいてキャッシュ戦略を割り当てたりできます。
Nuxtサーバーは、対応するミドルウェアを自動的に登録し、Nitroキャッシングレイヤーを使用してルートをキャッシュハンドラーでラップします。
export default defineNuxtConfig({
routeRules: {
// Homepage pre-rendered at build time
'/': { prerender: true },
// Products page generated on demand, revalidates in background, cached until API response changes
'/products': { swr: true },
// Product pages generated on demand, revalidates in background, cached for 1 hour (3600 seconds)
'/products/**': { swr: 3600 },
// Blog posts page generated on demand, revalidates in background, cached on CDN for 1 hour (3600 seconds)
'/blog': { isr: 3600 },
// Blog post page generated on demand once until next deployment, cached on CDN
'/blog/**': { isr: true },
// Admin dashboard renders only on client-side
'/admin/**': { ssr: false },
// Add cors headers on API routes
'/api/**': { cors: true },
// Redirects legacy urls
'/old-page': { redirect: '/new-page' }
}
})
ルートルール
使用できるさまざまなプロパティは次のとおりです。
redirect: string
- サーバーサイドのリダイレクトを定義します。ssr: boolean
- アプリのセクションのHTMLのサーバーサイドレンダリングを無効にし、ssr: false
を使用してブラウザーでのみレンダリングするようにします。cors: boolean
-cors: true
でcorsヘッダーを自動的に追加します -headers
で上書きすることにより、出力をカスタマイズできます。headers: object
- 特定のヘッダーをサイトのセクション(たとえば、アセット)に追加します。swr: number | boolean
- サーバー応答にキャッシュヘッダーを追加し、構成可能なTTL(Time To Live)のためにサーバーまたはリバースプロキシにキャッシュします。Nitroのnode-server
プリセットは、完全な応答をキャッシュできます。TTLが期限切れになると、ページがバックグラウンドで再生成されている間、キャッシュされた応答が送信されます。trueが使用されると、MaxAgeなしでstale-while-revalidate
ヘッダーが追加されます。isr: number | boolean
- 動作はswr
と同じですが、これをサポートするプラットフォーム(現在はNetlifyまたはVercel)で応答をCDNキャッシュに追加できます。true
を使用した場合、コンテンツはCDN内の次のデプロイまで保持されます。prerender: boolean
- ビルド時にルートをプリレンダリングし、静的アセットとしてビルドに含めます。experimentalNoScripts: 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 3を強化するサーバーエンジンであるNitroのおかげで可能です。Node.js、Deno、Cloudflare Workersなどのクロスプラットフォームサポートを提供します。
現在、ESRを活用できるプラットフォームは次のとおりです。
- git統合と
nuxt build
コマンドを使用して、構成なしで Cloudflare Pages nuxt build
コマンドとNITRO_PRESET=vercel-edge
環境変数を使用して、Vercel Edge Functionsnuxt build
コマンドとNITRO_PRESET=netlify-edge
環境変数を使用して、Netlify Edge Functions
ルートルールを使用してエッジサイドレンダリングを使用する場合、ハイブリッドレンダリングを使用できることに注意してください。
上記で言及したプラットフォームの一部にデプロイされたオープンソースの例を調べることができます。