<NuxtIsland>
Nuxtは、クライアント側のJSなしで非インタラクティブなコンポーネントをレンダリングするための<NuxtIsland>コンポーネントを提供します。
アイランドコンポーネントをレンダリングする際、アイランドコンポーネントの内容は静的であるため、クライアント側にはJSがダウンロードされません。
アイランドコンポーネントのプロップスを変更すると、アイランドコンポーネントの再レンダリングのために再フェッチがトリガーされます。
アプリケーションのグローバルスタイルはレスポンスと共に送信されます。
サーバー専用コンポーネントは内部で<NuxtIsland>を使用します。
Props
name: レンダリングするコンポーネントの名前。- type:
string - required
- type:
lazy: コンポーネントを非ブロッキングにします。- type:
boolean - default:
false
- type:
props: レンダリングするコンポーネントに送信するプロップス。- type:
Record<string,>
- type:
source: レンダリングするアイランドを呼び出すリモートソース。- type:
string
- type:
- dangerouslyLoadClientComponents: リモートソースからコンポーネントをロードするために必要です。
- type:
boolean - default:
false
- type:
リモートアイランドには、nuxt.configでexperimental.componentIslandsを'local+remote'に設定する必要があります。リモートサーバーのJavaScriptを信頼できないため、dangerouslyLoadClientComponentsを有効にすることは強く推奨されません。
デフォルトでは、コンポーネントアイランドは~/components/islands/ディレクトリからスキャンされます。そのため、~/components/islands/MyIsland.vueコンポーネントは<NuxtIsland name="MyIsland" />でレンダリングできます。
Slots
スロットは宣言されていればアイランドコンポーネントに渡すことができます。
すべてのスロットはインタラクティブです。なぜなら、親コンポーネントがそれを提供するからです。
いくつかのスロットは特別なケースのためにNuxtIslandに予約されています。
#fallback: アイランドがロードされる前(コンポーネントが遅延読み込みの場合)またはNuxtIslandがコンポーネントのフェッチに失敗した場合にレンダリングされるコンテンツを指定します。
Ref
refresh()- type:
() => Promise<void> - description: サーバーコンポーネントを再フェッチして強制的に再フェッチします。
- type:
Events
error- parameters:
- error:
- type:
unknown
- type:
- error:
- description:
NuxtIslandが新しいアイランドのフェッチに失敗したときに発生します。
- parameters:
tips
このセクションは公式ドキュメントの翻訳ではなく、本サイト独自の補足記事です。
Nuxt Island コンポーネントとは?
Nuxt Island コンポーネントは、Nuxtが提供する「アイランドアーキテクチャ」を実現するための仕組みです。これは、ページ全体をクライアント側でJavaScriptを動かしてレンダリングするのではなく、静的な部分はサーバーでレンダリングしつつ、必要な部分だけをインタラクティブにするという考え方に基づいています。
この仕組みにより、ページの初期表示速度が向上し、不要なJavaScriptのダウンロードや実行を減らせるため、パフォーマンス改善やSEO対策に効果的です。特に大規模なアプリケーションや、静的コンテンツと動的コンテンツが混在するサイトで威力を発揮します。
まず結論:Nuxt Island コンポーネントのポイント
- 静的なコンテンツはクライアント側のJavaScriptなしでレンダリングされるため、初期表示が高速
- 必要に応じてインタラクティブな部分だけをクライアントで動的に動かせる
- コンポーネントのプロップス変更で再フェッチ・再レンダリングが可能
- 遅延読み込み(lazy)もサポートし、非ブロッキングでの表示が可能
- リモートソースからのコンポーネント読み込みも設定次第で対応可能
- スロットを使って柔軟にコンテンツを差し替えられる
いつ使うべきか?使わない方がよいケース
使うべきケース
- ページの大部分が静的コンテンツで、部分的にだけ動的なUIが必要な場合
- 初期表示速度を重視し、不要なクライアントJavaScriptの読み込みを避けたい場合
- SEOを意識しつつ、ユーザー体験を損なわないインタラクティブ性を実現したい場合
- コンポーネントの状態がサーバー側で管理されており、クライアント側での再フェッチが必要な場合
使わない方がよいケース
- ページ全体が高度にインタラクティブで、クライアント側での状態管理が中心の場合
- クライアントでのみ動作するライブラリやプラグインを多用している場合
- リアルタイム更新や頻繁なユーザー操作に即応する必要があるUI
実務でよくあるユースケースとサンプルコード
1. 静的な記事ページに動的なコメント欄を組み込む
記事本文はサーバーで静的にレンダリングし、コメント欄だけをNuxt Islandで動的に読み込むことで、初期表示を高速化しつつコメント投稿機能を実現。
<template>
<article>
<h1>{{ article.title }}</h1>
<div v-html="article.content" />
<NuxtIsland name="CommentSection" :props="{ postId: article.id }" />
</article>
</template>
<script setup>
const article = await fetchArticle() // サーバーで取得
</script>
2. 遅延読み込みでパフォーマンス最適化
ユーザーがスクロールしてコメント欄が画面に近づいたときだけ読み込む設定。
<NuxtIsland name="CommentSection" :props="{ postId: article.id }" lazy />
3. リモートコンポーネントの読み込み(実験的機能)
別サーバーで管理されているコンポーネントを安全に読み込む場合。
<NuxtIsland
name="RemoteWidget"
source="https://remote-server.com/api/widget"
:dangerouslyLoadClientComponents="false"
/>
よくある落とし穴・注意点
SSRとHydrationのズレに注意
Nuxt Islandはサーバーで静的にレンダリングされるため、クライアント側でのHydration(再活性化)時に状態の不一致が起こると警告や表示崩れが発生します。プロップスの管理や状態の同期に注意が必要です。
パフォーマンス面の考慮
- 遅延読み込みを活用しないと、不要なコンポーネントまで先に読み込んでしまい、初期表示が遅くなることがあります。
- リモートコンポーネントの読み込みはネットワーク遅延や信頼性の問題があるため、
dangerouslyLoadClientComponentsの使用は慎重に。
スロットの扱い
スロットはインタラクティブですが、親コンポーネントが提供するため、スロット内の状態管理も考慮する必要があります。特にフェッチ失敗時のfallbackスロットは必ず用意しておくとUXが向上します。
まとめ
Nuxt Island コンポーネントは、静的レンダリングのメリットを活かしつつ、必要な部分だけを動的に扱える強力な機能です。初期表示の高速化やSEO対策に効果的で、実務でも記事ページのコメント欄やウィジェットの遅延読み込みなどで活用されています。一方で、SSRとCSRの状態同期やパフォーマンス面の注意も必要です。適切に使いこなすことで、ユーザー体験と開発効率の両立が可能になります。
Nuxt Island はサーバー専用コンポーネントの内部でも利用されているため、Nuxtの最新機能を理解する上で押さえておくと良いでしょう。
※このページは Nuxt.js 公式ドキュメントの翻訳ページです。
公式ドキュメントの該当ページはこちら:
https://nuxt.com/docs/3.x/api/components/nuxt-island