レンダリングモード

Nuxt は様々なレンダリングモードをサポートしています。
具体的には、ユニバーサルレンダリング、クライアントサイドレンダリング、ハイブリッドレンダリングがあります。

デフォルトでは、ユニバーサルレンダリングが選択されています。
また、これらは nuxt.config で簡単に切り替えることができます。

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

ユニバーサルレンダリングでは、サーバーが完全にレンダリングされた HTML を返します。
これにより、ユーザーはアプリケーションのコンテンツをすぐに取得することができます。

また、ブラウザ上で HTML を読み込んだ後、インタラクションを必要とする動的な UI を構築するためにブラウザ上で JavaScript コードを読み込みます。
このことを「ハイドレーション」と呼びます。

この例では app.vuecount と言うステートをコンソールに出力しています。
このページにアクセスした際にターミナル(サーバー)とブラウザのコンソールの両方でこの出力を確認することができます。

これはつまり、Nuxt が HTML をサーバー上で生成するために Vue.js のコードをサーバー上で実行し、その後ブラウザでも同じコードが実行されていることを意味します。
これゆえに「ユニバーサルレンダリング」と呼ばれています。

ユニバーサルレンダリングの利点と欠点は主に以下の通りです。

利点

  • パフォーマンス
    サーバーサイドで HTML を生成し、それをブラウザが読み込むため、ブラウザ上で JavaScript によってコンテンツを生成するよりも高速です。
  • 検索エンジン最適化 (SEO)
    Web クローラはページのコンテンツを直接インデックスできるため、SEO に有利です。

欠点

  • 開発の制約
    サーバーサイドとクライアントサイドでシームレスに動作するコードを書くためにいくつかの制約があります。
  • コスト
    サーバーを必要とするため、サーバーの稼働コストがかかります。

より詳細な説明については 公式ドキュメント を参照してください。

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

nuxt.configssr: false を設定することで、クライアントサイドレンダリングを有効にすることができます。

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

クライアントサイドレンダリングでは、アプリケーションをブラウザ上でレンダリングします。
ブラウザが現在のインターフェイスを作成するための命令を含むすべての JavaScript コードをダウンロードして解析した後、HTML 要素を生成します。

クライアントサイドレンダリングの利点と欠点は主に以下の通りです。

利点

  • 開発スピード
    サーバーサイドとのシームレスな動作を要求しないため、ブラウザで動作することだけを考慮して開発することができます。
  • 安価
    サーバーを必要としないため、インフラストラクチャのコストがかかりません。
  • オフライン
    コードはすべてブラウザで実行されるため、インターネットが利用できない状態でもうまく動作し続けることができます。

欠点

  • パフォーマンス
    ユーザーはブラウザが JavaScript ファイルをダウンロード、解析、実行するのを待たなければなりません。それらに時間がかかり、ユーザーの体験に影響を与える可能性があります。
  • 検索エンジン最適化 (SEO)
    クライアントサイドレンダリングで配信されたコンテンツのインデックス化と更新には時間がかかるため、サーバーレンダリングの HTML ドキュメントと比べ SEO に不利です。

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

Nuxt ではルートのルールを設定することにより、ルートごとに異なるキャッシュ ルールとレンダリングモードを選択することができます。

設定は nuxt.configrouteRules オプションで行います。

詳細は 公式ドキュメント を参照してください。

export default defineNuxtConfig({
  routeRules: {
    // Homepage pre-rendered at build time
    '/': { prerender: true },
    // 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 },
  }
})

チャレンジ

クライアントサイドレンダリングを設定し、Vue.js のコードがブラウザ上のみで実行されることを確認してみましょう。

そのためには:

  1. nuxt.configssr: false を設定します。
  2. app.vuecount と言うステートをコンソールに出力します。
  3. ターミナルでコンソールの出力が行われていないことを確認します。
  4. ブラウザの開発者ツールを開き、コンソールの出力を確認します。

次に、ハイブリッドレンダリングを設定し、ルートごとに異なるキャッシュ ルールとレンダリングモードを選択することができることを確認してみましょう。

そのためには:

  1. app.vueNuxtPage コンポーネントを使って、ページをレンダリングします。
  2. /pages/index.vue/pages/foo.vue で、script setup 内コンソールの出力を行います。(内容は任意のもので構いません)
  3. nuxt.configrouteRules を設定し、//foo に対して異なるキャッシュ ルールとレンダリングモードを設定します。
    今回は、/foossr: false を設定してみましょう。
  4. / にアクセスし、コンソールの出力がサーバーとクライアントの両方で行われていることを確認します。
  5. /foo にアクセスし、コンソールの出力がブラウザのみで行われていることを確認します。

レンダリングモードの動作の確認は、実際には console の出力場所だけではなく、開発者ツールのネットワークタブなどを使って、 リクエストの挙動を確認することも重要です。

ユニバーサルレンダリングの場合はサーバーが HTML を生成するため、ネットワークタブを確認してみるとコンテンツ内容 (主に <div id="__nuxt"> 内)が完全なものになっているのに対し、クライアントサイドレンダリングの場合は、HTML が空の状態で JavaScript によってコンテンツが生成されていることが確認できます。
(ダウンロードした JavaScript も別のリクエストとして観測することができます)

レイアウト
Nuxt は UI パターンを再利用可能にするための機能を提供しています。 layout は ~/layouts デイレクトリに実装され、app.vue で NuxtLayout を使用することで適応されます。 layout は各ページごとに definePageMeta を通して選択することができます。
状態管理
Vue.js での状態管理 (State Management) とは、アプリケーションでリアクティブな状態 (ステート) を管理することを言います。Vue.js 公式ドキュメント 状態管理
Files
Editor
Initializing WebContainer
Mounting files
Installing dependencies
Starting Nuxt server
Waiting for Nuxt to ready
Terminal