WSL2 で Vite の HMR が効かない・ファイル変更が反映されない時の原因と対策【hot reload / inotify / polling】

公開日:2026-08-24/カテゴリ:Vite・WSL2・開発環境/AnchorUp 技術ブログ

WSL2 で Vite HMR が効かない症状

WSL2 環境で npm run dev を起動してブラウザで開発中、ファイルを保存してもブラウザが自動更新されない——この問題に直面したことがある方は多いはずです。

具体的な症状:

原因は一つ:inotify が Windows ファイルシステムの変更を検知できない

Vite はデフォルトで Linux の inotify システムコールを使ってファイルの変更を監視しています。しかし WSL2 の /mnt/c/ ディレクトリ(Windows の NTFS ファイルシステムのマウント)では、inotify がファイル変更イベントを受け取れません。

原因:WSL2 と inotify の仕組み

WSL2 はその名の通り、Windows 上で動く Linux 仮想マシンです。ファイルシステムは大きく 2 種類存在します:

ファイルシステム パス例 inotify
WSL2 ネイティブ(ext4) ~/projects/myapp ✅ 動作する
Windows マウント(NTFS) /mnt/c/Users/.../myapp ❌ 検知できない

Windows 側のエディタ(VSCode の Remote WSL 含む)がファイルを保存しても、NTFS 側の変更イベントは WSL2 の Linux カーネルには届きません。Vite の chokidar(ファイル監視ライブラリ)が使う inotify がイベントを受け取れないため、HMR が発火しません。

解決策1:プロジェクトを WSL2 ネイティブファイルシステムに移す(最善策)

これが唯一の根本解決です。 パフォーマンスも大幅に改善されます。

# NG: Windows ファイルシステム上のパス
# /mnt/c/Users/yourname/projects/myapp

# OK: WSL2 ネイティブパス
# ~/projects/myapp
# /home/yourname/projects/myapp

移行手順:

# WSL2 ターミナルで
mkdir -p ~/projects
cp -r /mnt/c/Users/yourname/projects/myapp ~/projects/myapp
cd ~/projects/myapp
npm install  # node_modules を再生成
npm run dev

VSCode を使っている場合は Remote WSL 拡張機能でそのままアクセスできます:

cd ~/projects/myapp
code .  # WSL2 側からプロジェクトを開く

パフォーマンスの差: NTFS マウントより ext4 ネイティブの方が npm install で 5〜10 倍速くなるケースもあります。HMR 以外の理由でもネイティブファイルシステムへの移行を強く推奨します。

解決策2:polling モードを有効にする

どうしても Windows ファイルシステム上で作業する場合のバンドエイド的対策です。chokidar のポーリングモードを有効にすると、inotify に頼らず一定間隔でファイルの変更を確認します。

// vite.config.ts
import { defineConfig } from 'vite'

export default defineConfig({
  server: {
    watch: {
      usePolling: true,
      interval: 1000, // ポーリング間隔(ミリ秒)
    },
  },
})

環境変数でも制御できます:

# .env.local
CHOKIDAR_USEPOLLING=true
CHOKIDAR_INTERVAL=1000

デメリット: ファイル数が多いプロジェクトでは CPU 使用率が上がります。node_modules を監視対象から外す設定を合わせて行うと軽減できます:

// vite.config.ts
export default defineConfig({
  server: {
    watch: {
      usePolling: true,
      interval: 1000,
      ignored: ['**/node_modules/**', '**/.git/**'],
    },
  },
})

解決策3:HMR の WebSocket 接続設定を修正する

HMR 自体は動いているのにブラウザに届かない場合、WebSocket の接続設定の問題かもしれません。WSL2 の IP アドレスと Windows ブラウザ側の接続ホストが食い違うことがあります。

// vite.config.ts
export default defineConfig({
  server: {
    host: '0.0.0.0', // WSL2 内サーバーを Windows から到達可能にする
    hmr: {
      host: 'localhost', // ブラウザが接続する HMR WebSocket のホスト
    },
  },
})

WSL2 の IP が動的に変わる場合(再起動のたびに変わる)は、localhost を明示することで安定します。

解決策4:inotify の watch 上限を増やす

大規模プロジェクトで「too many open files」エラーが出て HMR が止まる場合、inotify のウォッチ数上限に達している可能性があります。

現在の上限を確認:

cat /proc/sys/fs/inotify/max_user_watches
# デフォルト: 8192

上限を増やす(WSL2 内で実行):

# 一時的に増やす(再起動で元に戻る)
sudo sysctl fs.inotify.max_user_watches=524288

# 永続的に増やす
echo 'fs.inotify.max_user_watches=524288' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

WSL2 の場合、/etc/wsl.conf に設定を書くことでも永続化できます:

# /etc/wsl.conf
[boot]
command = sysctl -w fs.inotify.max_user_watches=524288

Docker + WSL2 の場合の追加設定

Docker Compose を WSL2 で使っている場合、コンテナ内の Vite にも同様の問題が起きます。

# docker-compose.yml
services:
  frontend:
    image: node:20-alpine
    volumes:
      - .:/app
    working_dir: /app
    command: npm run dev
    ports:
      - "5173:5173"
    environment:
      - CHOKIDAR_USEPOLLING=true
      - CHOKIDAR_INTERVAL=1000

Vite の設定でホストを指定することも必要です(コンテナ外からアクセスするため):

// vite.config.ts
export default defineConfig({
  server: {
    host: true, // '0.0.0.0' と同等
    port: 5173,
    watch: {
      usePolling: true,
    },
  },
})

症状・原因・対策の一覧

症状 原因 対策
ファイル保存しても反応しない /mnt/c/ に保存、inotify 未動作 WSL2 ネイティブパスに移動
Connected なのに更新されない 同上、またはポーリング未設定 usePolling: true を設定
ブラウザが WS 接続エラー WSL2 IP アドレスの不一致 server.hmr.host を localhost に
起動直後は動くが止まる inotify watch 上限超過 max_user_watches を増やす
Docker 内でも効かない コンテナも NTFS 経由 CHOKIDAR_USEPOLLING=true

まとめ

WSL2 で Vite の HMR が効かない問題は、inotify が Windows NTFS ファイルシステムのイベントを受け取れないことが根本原因です。

推奨する対処の優先順位:

  1. プロジェクトを WSL2 ネイティブパス(~/projects/)に移す → 根本解決かつパフォーマンス向上
  2. usePolling: true を設定する → 移行できない場合のバンドエイド
  3. server.hmr.host: 'localhost' を指定する → WebSocket 接続の安定化
  4. max_user_watches を増やす → 大規模プロジェクトでの上限対策

特に理由がなければ解決策1一択です。WSL2 ネイティブファイルシステムへの移行は HMR の修正だけでなく、npm install や git status の速度も劇的に改善します。

技術ブログの記事一覧へ