Browsersyncを非Docker環境とDocker環境の両方で使いたい

お世話になっております。矢ヶ崎です。

最近、とあるシステムのヘルプをするにあたって、既存の React プロジェクトの開発環境を Docker 化させたときに、 Browsersync がうまく動かずハマったので、ここに記しておきます。

もともと、 Docker を使わずに開発していたのもあり、 Docker を使わないでの開発環境も引き続き必要という状況だったため、 Browsersync 側にはなんの変更も加えずに動くようにするのに苦労しました。

SPAベースでできているため、 nginx の裏にはフロントエンドとバックエンドの両方を配置し、パスベースで振り分けるようにしております。

Browser
 => nginx
   => /api/
       => port 3000 Backend
   => /
       => port 2000 Frontend

ただ、これだけだといい感じに Browsersync が動きません。既存のBrowsersyncの設定(抜粋)はこんな感じです。

      new BrowserSyncPlugin(
        {
          https: options.tls,
          host: 'localhost',
          port,
          proxy: {
            target: `http${options.tls ? 's' : ''}://localhost:9060`,
            proxyOptions: {
              changeOrigin: false
            }
          },

こうなると、ブラウザは localhost:9060 に Browsersync 的な接続しに行こうとします。そして、当然つながりません。もちろんここを変えるというのもあるのですが、今回はここは変更できません。なので、 nginx 側でいい感じにルーティングします。

まずは、 Port 9060 を listen するようにします。

    image: nginx:latest
    ports:
      - 80:80
      - 9060:9060

そして、Port 9060 に来た通信を Websocket ベースで Frontend の Port 2000 に飛ばしてあげます。

map $http_upgrade $connection_upgrade { 
    default upgrade;
    ''      close;
} 

server {
    listen 9060;
    server_name localhost;

    proxy_http_version 1.1;
    proxy_set_header Host $host;
    proxy_set_header Upgrade $http_upgrade; 
    proxy_set_header Connection $connection_upgrade;

    location / {
        proxy_pass http://docker-fe:2000;
    }
}

こんな感じで、既存の環境も動作させつつ、Dockerでも快適に開発ができるようになりました!

よかった〜