🐷

【Nuxt3】 プロキシ経由で HMR を使えるようにする

2024/07/27に公開

対応内容は基本的にこちらの記事と同様。

エラーと対応

画像のような環境にアクセスすると以下のようなエラーがブラウザのコンソールに表示される。

Mixed Content: The page at 'https://example.com/' was loaded over HTTPS, but attempted to connect to the insecure WebSocket endpoint 'ws://example.com/_nuxt/'. This request has been blocked; this endpoint must be available over WSS.

HMR では WebSocket 通信を利用しており、デフォルトのプロトコルは ws になっている。
HTTPS で通信する場合、wss プロトコルにする必要がある。

設定方法を調べると以下のような設定が出てくるが、自分の環境では反映されなかった。

nuxt.confg.ts
export default defineNuxtConfig({
  vite: {
    server: {
      hmr: {
        protocol: 'wss',
      },
    },
  },
})

代わりにこちらのスクラップを参考に以下のように修正する。

nuxt.config.ts
export default defineNuxtConfig({
  hooks: {
    'vite:extendConfig' (viteInlineConfig, env) {
      viteInlineConfig.server = {
        ...viteInlineConfig.server,
        hmr: {
          protocol: 'wss',
        },
      }
    },
  },
})

これで wss で通信をするようになったが、Docker コンテナのポートが開いていないため疎通に失敗する。

WebSocket connection to 'wss://example.com:24678/_nuxt/' failed:

ポート開放以外にもプロキシサーバーでリクエストをさばけるように設定する必要がある。

nuxt.config.ts
export default defineNuxtConfig({
  hooks: {
    'vite:extendConfig' (viteInlineConfig, env) {
      viteInlineConfig.server = {
        ...viteInlineConfig.server,
        hmr: {
          protocol: 'wss',
          // クライアントが WebSocket サーバーに通信するときに使用するポート
          clientPort: 443,
          // WebSocket 通信時のパス(Nginx の設定と合わせれば何でもよい)
          path: 'hmr/',
        },
      }
    },
  },
})
site.conf
server {
    listen 443 ssl;
    ssl_certificate /etc/nginx/certs/server.crt;
    ssl_certificate_key /etc/nginx/certs/server.key;

    server_name local.profile.sayuprc.dev;

    location / {
        proxy_pass http://host.docker.internal:3001/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # 以下を追記
    # /_nuxt/hmr/ に来たアクセスは WebSocket サーバーに転送する
    location /_nuxt/hmr/ {
        # WebSocket 通信を行うサーバーはデフォルトの 24678 ポート
        proxy_pass http://host.docker.internal:24678/;
        # 以下の設定で WebSocket に対応する
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}
compose.yaml
services:
  node:
    image: example
    environment:
      LANG: ja_JP.UTF-8
      TZ: Asia/Tokyo
    tty: true
    ports:
      - 3000:3000
      - 24678:24678 # WebSocket 通信を行うサーバーのポート番号
    volumes:
      - ./src:/app

これで HMR が効くようになる。

参考

Nuxt 3.8 で HMR が効かなくなったときの対応方法
Docker+Nuxt3+SSL+Nginx-Proxy環境でHMRを使える様にする

GitHubで編集を提案

Discussion