layouts
Nuxtは共通のUIパターンを再利用可能なレイアウトに抽出するためのレイアウトフレームワークを提供します。
最高のパフォーマンスを得るために、このディレクトリに配置されたコンポーネントは使用時に非同期インポートを通じて自動的にロードされます。
レイアウトを有効にする
レイアウトは、app.vue に <NuxtLayout> を追加することで有効になります:
<template>
<NuxtLayout>
<NuxtPage />
</NuxtLayout>
</template>
レイアウトを使用するには:
- definePageMeta を使用してページに
layoutプロパティを設定します。 <NuxtLayout>のnameプロパティを設定します。
レイアウト名はケバブケースに正規化されるため、someLayout は some-layout になります。
レイアウトが指定されていない場合、layouts/default.vue が使用されます。
アプリケーションにレイアウトが1つしかない場合は、app.vue を使用することをお勧めします。
他のコンポーネントとは異なり、レイアウトには単一のルート要素が必要であり、Nuxtがレイアウト変更間のトランジションを適用できるようにする必要があります。このルート要素は <slot /> ではありません。
デフォルトレイアウト
~/layouts/default.vue を追加します:
<template>
<div>
<p>すべてのページで共有されるデフォルトのレイアウトコンテンツ</p>
<slot />
</div>
</template>
レイアウトファイル内では、ページのコンテンツは <slot /> コンポーネントに表示されます。
名前付きレイアウト
-| layouts/
---| default.vue
---| custom.vue
その後、ページで custom レイアウトを使用できます:
definePageMeta({
layout: 'custom'
})すべてのページのデフォルトレイアウトを直接上書きするには、<NuxtLayout> の name プロパティを使用します:
<script setup lang="ts">
// APIコールやログイン状態に基づいて選択することができます
const layout = "custom";
</script>
<template>
<NuxtLayout :name="layout">
<NuxtPage />
</NuxtLayout>
</template>
ネストされたディレクトリにレイアウトがある場合、レイアウトの名前はそのパスディレクトリとファイル名に基づき、重複するセグメントが削除されます。
| ファイル | レイアウト名 |
|---|---|
~/layouts/desktop/default.vue | desktop-default |
~/layouts/desktop-base/base.vue | desktop-base |
~/layouts/desktop/index.vue | desktop |
明確にするために、レイアウトのファイル名がその名前と一致することをお勧めします:
| ファイル | レイアウト名 |
|---|---|
~/layouts/desktop/DesktopDefault.vue | desktop-default |
~/layouts/desktop-base/DesktopBase.vue | desktop-base |
~/layouts/desktop/Desktop.vue | desktop |
レイアウトを動的に変更する
setPageLayout ヘルパーを使用して、レイアウトを動的に変更することもできます:
<script setup lang="ts">
function enableCustomLayout () {
setPageLayout('custom')
}
definePageMeta({
layout: false,
});
</script>
<template>
<div>
<button @click="enableCustomLayout">レイアウトを更新</button>
</div>
</template>
ページごとにレイアウトを上書きする
ページを使用している場合、layout: false を設定し、ページ内で <NuxtLayout> コンポーネントを使用することで完全に制御できます。
<script setup lang="ts">
definePageMeta({
layout: false,
})
</script>
<template>
<div>
<NuxtLayout name="custom">
<template #header> ヘッダーのテンプレートコンテンツ。 </template>
ページの残りの部分
</NuxtLayout>
</div>
</template>
ページ内で <NuxtLayout> を使用する場合、それがルート要素でないことを確認してください(またはレイアウト/ページトランジションを無効にする)。
tips
このセクションは公式ドキュメントの翻訳ではなく、本サイト独自の補足記事です。
Nuxtのレイアウト機能とは?〜何が嬉しいのか〜
Nuxtのレイアウト機能は、複数のページで共通して使うUIパターン(ヘッダー、フッター、サイドバーなど)を一元管理し、再利用できる仕組みです。これにより、各ページで同じコードを繰り返す必要がなくなり、開発効率が大幅に向上します。
また、レイアウトを切り替えることで、サイト内の異なるセクションごとに異なるデザインや構造を簡単に実装可能です。例えば、管理画面と一般ユーザー向けページでレイアウトを分けるといった使い方が典型的です。
さらに、Nuxtはレイアウトを非同期に自動でインポートするため、パフォーマンス面でも優れています。必要なレイアウトだけを読み込むことで初期ロードを軽くし、ユーザー体験を向上させます。
まず結論:Nuxtレイアウトのポイント
- レイアウトは
~/layoutsディレクトリに配置し、ファイル名がレイアウト名になる(ケバブケースに正規化) - ページごとに
definePageMetaのlayoutプロパティでレイアウトを指定可能 layouts/default.vueが指定なしのデフォルトレイアウトとして使われる<NuxtLayout>コンポーネントでレイアウトをラップし、ページコンテンツは<slot />で差し込む- 動的にレイアウトを切り替えたい場合は
setPageLayoutユーティリティを使う - ページ単位でレイアウト制御したい場合は
layout: falseにしてページ内で<NuxtLayout>を使う方法もある
いつ使うべき?使わない方がよいケースは?
使うべきケース
- 複数ページで共通のUI構造を持たせたいとき(例:共通ヘッダーやフッター)
- サイト内で複数の異なるデザインテンプレートを使い分けたいとき
- ページ遷移時にレイアウト単位でトランジションを適用したいとき
- 管理画面やユーザー向けページなど、役割ごとにUIを切り替えたいとき
使わない方がよいケース
- 単一ページアプリケーションでレイアウトの切り替えが不要な場合(
app.vueだけで十分) - ページごとに全く異なるUI構造を持ち、共通部分がほぼない場合(レイアウトの恩恵が薄い)
- レイアウトのルート要素制約(単一ルート要素)が合わず複雑な構造を必要とする場合
実務でよくあるユースケースとサンプルコード
1. デフォルトレイアウトで共通ヘッダー・フッターを実装
<!-- layouts/default.vue -->
<template>
<div>
<header>共通ヘッダー</header>
<main>
<slot />
</main>
<footer>共通フッター</footer>
</div>
</template>
すべてのページはこのレイアウトを自動的に使い、ヘッダー・フッターが共通化されます。
2. 管理画面用のカスタムレイアウトを作成し切り替え
<!-- layouts/admin.vue -->
<template>
<div class="admin-layout">
<nav>管理メニュー</nav>
<section>
<slot />
</section>
</div>
</template>
// pages/admin/dashboard.vue
<script setup lang="ts">
definePageMeta({
layout: 'admin'
})
</script>
管理画面のページだけadminレイアウトを使い、一般ページとUIを分けられます。
3. ページ内でレイアウトを完全制御したい場合
<!-- pages/custom.vue -->
<script setup lang="ts">
definePageMeta({
layout: false
})
</script>
<template>
<NuxtLayout name="custom">
<template #header>
<h1>カスタムヘッダー</h1>
</template>
<p>ページ固有のコンテンツ</p>
</NuxtLayout>
</template>
<!-- layouts/custom.vue -->
<template>
<div>
<header>
<slot name="header">デフォルトヘッダー</slot>
</header>
<main>
<slot />
</main>
</div>
</template>
ページごとにレイアウトの構造やスロットを柔軟に制御したい場合に有効です。
よくある落とし穴・注意点
1. レイアウトのルート要素は単一であること
Nuxtはレイアウトのルート要素を1つに限定しています。複数の兄弟要素を直接並べるとエラーになるため、必ず1つの親要素で囲みましょう。
2. レイアウトの非同期読み込みとパフォーマンス
~/layoutsに置いたレイアウトは自動的に非同期インポートされます。これにより初期ロードが軽くなりますが、動的に切り替える際はレイアウトの読み込み遅延に注意が必要です。ユーザー体験を損なわないよう、必要に応じてプリフェッチやローディングUIを検討しましょう。
3. SSRとHydrationのズレに注意
レイアウト内でクライアント専用の処理や状態を扱う場合、SSR時とCSR時で差異が出るとHydrationエラーが発生します。例えば、ブラウザのAPIを使う処理はprocess.clientで囲むなど工夫が必要です。
4. ページ内で<NuxtLayout>を使う場合のトランジション制御
ページ内でlayout: falseにして<NuxtLayout>を使うと、Nuxtの標準トランジションが効かなくなることがあります。必要に応じてトランジションを無効化する設定やカスタム実装を検討してください。
まとめ
Nuxtのレイアウト機能は、共通UIの再利用や複数デザインの切り替えを簡単に実現できる強力な仕組みです。正しく使えば開発効率と保守性が大幅に向上しますが、単一ルート要素の制約やSSR/CSRの差異など注意点もあります。
実務ではデフォルトレイアウトの活用から始め、必要に応じてカスタムレイアウトや動的切り替えを取り入れるのがおすすめです。落とし穴を理解しつつ、Nuxtのレイアウト機能を最大限に活用しましょう。
レイアウト名はケバブケースに正規化されるため、ファイル名とレイアウト名の対応を意識すると管理が楽になります。
※このページは Nuxt.js 公式ドキュメントの翻訳ページです。
公式ドキュメントの該当ページはこちら:
https://nuxt.com/docs/3.x/guide/directory-structure/layouts