Next.js 15 から 16 へのアップデートで遭遇した問題と対処法をまとめてみた
はじめに
先日Next.js 15から16へのプロジェクトのアップデートを行いました。
その過程でいくつかの問題に遭遇したため、それらの問題と対処法を共有します。
特にParallel RoutesやIntercepting Routesを使用しているプロジェクトでは、型チェックの厳密化により複数のエラーが発生する可能性があります。
あくまで私の環境で出た問題と、それに対する対処法になります。
環境情報
- Next.js: 15.4.x → 16.1.x
- TypeScript: 5.9.x
- React: 19.x
発生した問題と対処法
1. middleware → proxy への変更
Next.js 16 では、middleware.ts というファイル名が非推奨になり、proxy.ts に変更されました。
エラーメッセージ
ビルド時に以下の警告が表示されます:
⚠ The "middleware" file convention is deprecated. Please use "proxy" instead.
Learn more: https://nextjs.org/docs/messages/middleware-to-proxy
対処法
- ファイル名を
middleware.ts→proxy.tsに変更 - エクスポートする関数名を
middleware→proxyに変更
// Before: src/middleware.ts
export function middleware(request: NextRequest) {
// ...
}
// After: src/proxy.ts
export function proxy(request: NextRequest) {
// ...
}
config オブジェクトの形式は変更不要です:
export const config = {
matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'],
}
注意: proxy.ts は Node.js ランタイムでのみ動作し、Edge Runtime はサポートされていません。Edge Runtime を使用している場合は、middleware.ts を維持する必要があります。
2. Parallel Routesの型チェック厳密化
Next.js 16 では、Layout コンポーネントの Props 型がディレクトリ構造に基づいて厳密にチェックされるようになりました。
エラーメッセージ
Type error: Type 'typeof import(".../[id]/layout")' does not satisfy the constraint 'LayoutConfig<"/[lang]/products/[id]">'.
Types of property 'default' are incompatible.
Property 'modals' is missing in type 'LayoutProps<"/[lang]/products/[id]">' but required in type '{ tabs: ReactNode; modals: ReactNode; }'.
原因
Layout コンポーネントで modals という Parallel Route スロットを受け取っているにもかかわらず、対応する @modals ディレクトリ(または default.tsx)が存在しない場合に発生します。
対処法
該当する Parallel Route ディレクトリに default.tsx を追加します:
app/
└── [lang]/
└── products/
└── [id]/
├── layout.tsx # modals を受け取る
├── page.tsx
├── @tabs/
│ └── ...
└── @modals/ # 追加
└── default.tsx # 追加
default.tsx の内容:
// app/[lang]/products/[id]/@modals/default.tsx
const Default = () => null
export default Default
Parallel Route の default.tsx は、そのスロットがアクティブでない場合にレンダリングされるフォールバックコンポーネントです。null を返すことで、何も表示しないようにできます。
3. Layout と Page の Props 型分離
Next.js 16 では、Layout コンポーネントと Page コンポーネントで受け取る Props が厳密に区別されるようになりました。
エラーメッセージ
Property 'searchParams' is missing in type 'LayoutProps<"/[lang]/products/[id]">' but required in type 'ProductDetailPageProps'.
原因
Layout コンポーネントは searchParams を受け取りませんが、Page 用の Props 型を Layout で使用していた場合にエラーが発生します。
対処法
Layout 専用の型を定義し、Page の型と分離します:
// Before: Layout と Page で同じ型を使用
type ProductDetailPageProps = {
params: Promise<{ lang: string; id: string }>
searchParams: Promise<{ tab?: string }>
children: ReactNode
}
export default async function ProductDetailLayout({
params,
searchParams, // Layout では使えない
children,
}: ProductDetailPageProps) {
// ...
}
// After: Layout 専用の型を定義
type ProductDetailLayoutProps = {
params: Promise<{ lang: string; id: string }>
tabs: ReactNode
modals: ReactNode
children: ReactNode
}
type ProductDetailPageProps = {
params: Promise<{ lang: string; id: string }>
searchParams: Promise<{ tab?: string }>
}
export default async function ProductDetailLayout({
params,
tabs,
modals,
children,
}: ProductDetailLayoutProps) {
// ...
}
export default async function ProductDetailPage({
params,
searchParams,
}: ProductDetailPageProps) {
// ...
}
4. Intercepting Routes + Parallel Routes の型問題
Intercepting Routes 内で Parallel Routes を使用している場合、Next.js 16 のビルド時に自動生成される型定義ファイル(.next/types/)が正しく型を解釈できないことがあります。
エラーメッセージ
.next/types/validator.ts(xxx,xx): error TS2344:
Type 'typeof import(".../(..)(..)items/[itemId]/layout")' does not satisfy
the constraint 'LayoutConfig<"/[lang]/items/[itemId]">'.
Property 'pages' is missing in type 'LayoutProps<"/[lang]/items/[itemId]">'
原因
Intercepting Routes((..)、(..)(..) など)内で Parallel Routes(@pages など)を使用している場合、Next.js の自動生成される型定義が Intercepting Routes を元のルートとして解釈してしまい、型の不整合が発生します。
例えば、以下のようなディレクトリ構造の場合:
app/
└── [lang]/
└── products/
└── [id]/
└── @modals/
└── (..)(..)items/ # items を intercept
└── [itemId]/
├── layout.tsx # @pages を使用
└── @pages/
└── default.tsx
この layout.tsx は /[lang]/products/[id]/@modals/(..)(..)items/[itemId] に存在しますが、型チェックでは /[lang]/items/[itemId] の型として検証されてしまいます。
対処法
tsconfig.json で .next/types/validator.ts を除外します:
{
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts",
".next/dev/types/**/*.ts"
],
"exclude": [
"node_modules",
".next/types/validator.ts"
]
}
注意: この方法は型チェックの一部を無効化するため、本来検出されるべきエラーが見逃される可能性があります。一部のケースにおける暫定的な対処法としてご検討ください。
まとめ
Next.js 15 から 16 へのアップデートで遭遇した主な問題は以下の通りです:
| 問題 | 対処法 |
|---|---|
| middleware → proxy | ファイル名・関数名を変更 |
| Parallel Routes の型チェック | @xxx/default.tsx を追加 |
| Layout/Page の Props 分離 | Layout 専用の型を定義 |
| Intercepting Routes + Parallel Routes | validator.ts を exclude |
特に Parallel Routes や Intercepting Routes を多用しているプロジェクト では、型チェックの厳密化により複数のエラーが発生する可能性があります。アップデート前にこれらの点を確認しておくことをお勧めします。









