Next.js のホットリロード(Fast Refresh)が効かないときの基本処方箋
Next.js のホットリロード(Fast Refresh)が効かないときの基本処方箋
Docker/WSL2/VM/ネットワークドライブなど ファイル更新イベントが取りこぼれやすい環境 では、Fast Refresh(いわゆるホットリロード)が反応しないことがあります。そんなとき、まず効くのが webpack の watchOptions でポーリング監視に切り替える 方法(=next dev を webpack 開発サーバで動かす前提)です。
結論:next.config.ts に watchOptions を追加
// next.config.ts
/** @type {import('next').NextConfig} */
const nextConfig = {
webpack: (config, { dev }) => {
if (dev) {
config.watchOptions = {
// イベント監視が不安定な環境向けにポーリングへ
poll: 1000, // 1秒ごとに差分チェック
aggregateTimeout: 200, // 変更連打時に200ms待ってまとめて再ビルド
// ignored: /node_modules/, // 必要なら監視除外(既定で除外)
};
}
return config;
},
};
module.exports = nextConfig;
-
poll: OS のファイルイベントに頼らず 定期的にファイル更新を走査。 -
aggregateTimeout: 変更が連続したときに 再ビルドを少し待ってまとめるデバウンス。
注意:
--turbo(Turbopack)起動時はこのwatchOptionsは効きません。監視が怪しい環境では 一旦 webpack 開発サーバ(next dev)に戻して安定化 するのが手堅いです。
仕組みの要点(なぜ効くのか)
Next.js の Fast Refresh は「ファイル変更の検知 → 差分ビルド → ブラウザへ更新」を行います。変更検知はバンドラ側(webpack なら watchpack)が担うため、ネットワーク越しのマウントや仮想環境でイベントが落ちる 場合は、ポーリングに切り替えるのが定石です。
Turbopack と webpack の切り替え指針
-
Turbopack(
next dev --turbo):高速で快適。ただし一部環境でファイル監視が不安定なことがある。 -
webpack(
next dev):保守的で互換性が広い。困ったらまずこちらに戻しwatchOptionsを当てる。
package.json 例:
{
"scripts": {
"dev": "next dev", // webpack dev(watchOptions 有効)
"dev:turbo": "next dev --turbo"
}
}
環境変数で“全体スイッチ”を掛ける(Docker/WSL2 の定番)
next.config.js を触らずに、watchpack をポーリング強制する方法も有効です(Compose などで一括適用したいときに便利)。
.env.local(または Compose の environment)に設定:
WATCHPACK_POLLING=true
Docker Compose 例:
services:
web:
image: node:20
working_dir: /app
volumes:
- .:/app
- /app/node_modules
environment:
- WATCHPACK_POLLING=true
command: sh -c "npm i && npm run dev"
ports:
- "3000:3000"
補足:ポーリングは CPU を使うため、必要に応じて
poll間隔を1000 → 2000〜5000msなどへ調整。ignoredのチューニングも検討。
周辺テク(安定化の小ワザ)
1) onDemandEntries の調整(開発サーバのページ保持)
開発サーバが保持するビルド済みページの キャッシュ期間/数 を微調整できます。重い環境での再ビルド頻度を抑制。
// next.config.js
module.exports = {
onDemandEntries: {
maxInactiveAge: 25 * 1000, // 既定: 25s
pagesBufferLength: 5 // 既定: 5
},
};
2) .next のキャッシュを一度クリア
挙動が乱れたら .next/ を削除 → npm run dev 再起動。
3) 起動コマンドの取り違えに注意
next build && next start は 本番サーバ。HMR/Fast Refresh は next dev でのみ有効です。
Fast Refresh が“フルリロード”に落ちる条件
Fast Refresh 自体は生きていても、以下では フルページリロード になります:
- 匿名コンポーネントや、コンポーネント以外のエクスポートが同ファイルに混在
- コンポーネント名が PascalCase でない …など
この条件に当たっていないかもチェックしておくと切り分けが早いです。
最短チェックリスト(現場版)
-
next devで起動しているか(next startではない) -
WATCHPACK_POLLING=trueを設定(Docker/WSL2/リモートFSなど) - それでもダメなら Turbopack を外して webpack dev に切替え、
watchOptions.pollを設定 -
.next/を削除して再起動 - それでも不安定なら
poll間隔やignoredを調整
参考リンク(公式・一次情報中心)
- webpack: Watch / WatchOptions
https://webpack.js.org/configuration/watch/ - Next.js:
next.config.js/ webpack 拡張
https://nextjs.org/docs/app/api-reference/config/next-config-js/webpack - Next.js: Fast Refresh の仕組み
https://nextjs.org/docs/architecture/fast-refresh - Next.js: Fast Refresh がフルリロードになる条件
https://nextjs.org/docs/messages/fast-refresh-reload - Next.js:
onDemandEntries(開発時のページ保持)
https://nextjs.org/docs/app/api-reference/config/next-config-js/onDemandEntries - Next.js CLI(
next dev/next build/next start)
https://nextjs.org/docs/app/api-reference/cli/next - watchpack(webpack の監視層。
WATCHPACK_POLLINGに言及)
https://github.com/webpack/watchpack
Discussion