概要
- Vite を使って Rails アプリに React を導入する方法。
- Docker 環境で起こった WebSocket/HMR のエラーとその対処法
前提条件
- Rails7.2
- React19.0
- vite 最新
ディレクトリ構成
/rails_app
├── Dockerfile
├── docker-compose.yml
├── app
手順
- Vite Rails の導入
- React のインストール
- Vite 設定ファイルの編集
- application.html.erbの修正
実装
https://vite-ruby.netlify.app/guide/
の手順通りに進めます
gem 'vite_rails'
を記述した後、以下を順番に実行します
bundle install
bundle exec vite install #Vite環境をRailsに組み込む
yarn add react react-dom #React本体
yarn add -D @vitejs/plugin-react #ViteでReactを使うためのplugin
yarn addでreactとreact-domを入れる
yarn add react@latest react-dom@latest
yarn add -D @vitejs/plugin-react
vite.config.ts
にreact()を追記します
import { defineConfig } from 'vite'
import RubyPlugin from 'vite-plugin-ruby'
import react from "@vitejs/plugin-react"
export default defineConfig({
plugins: [
RubyPlugin(),
react()
],
})
application.html.erb
を修正します
<!DOCTYPE html>
<html>
<head>
<title>ReactOnRails</title>
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= vite_client_tag %>
<%= vite_react_refresh_tag %>
<%= vite_javascript_tag 'application.jsx' %>
</head>
<body>
<%= yield %>
</body>
</html>
-
vite_client_tag
→ Vite の HMR クライアント読み込み(開発中のみ) -
vite_react_refresh_tag
→ React コンポーネントの状態を保ったままリロードするためのタグ(React の Fast Refresh 対応) -
vite_javascript_tag 'application'
→ エントリポイントを読み込み(app/javascript/entrypoints/application.jsx
を指す)
参考記事
以下のエラーが起こっていた
WebSocket connection to 'ws://0.0.0.0:3036/vite-dev/?token=v6TJU8fD7wce' failed:
- 0.0.0.0は「すべてのネットワークインターフェースでリッスンする」という意味のIPアドレス
- クライアント(ブラウザ)が接続する際のアドレスとしては機能しない
- localhostに変更することで、ブラウザは実際にアクセス可能なアドレスに接続できるようになる
矢じるし - サーバー側(Vite)では「すべてのインターフェースでリッスン」するために
0.0.0.0
を使う - クライアント側(ブラウザ)では実際に接続できるアドレス(
localhost
)を使う
vite.json
"development": {
"autoBuild": true,
"host": "0.0.0.0",
"publicOutputDir": "vite-dev",
"port": 3036
}
docker-compose.yml
environment:
TZ: Asia/Tokyo
VITE_RUBY_HOST: "0.0.0.0"
VITE_RUBY_PORT: 3036
vite.config
import { defineConfig } from 'vite'
import RubyPlugin from 'vite-plugin-ruby'
import react from "@vitejs/plugin-react"
export default defineConfig({
server: {
host: '0.0.0.0',
port: 3036,
hmr: {
protocol: 'ws',
host: 'localhost',
port: 3036,
}
},
plugins: [
RubyPlugin(),
react()
],
})
参考記事
VITE_RUBY_HOSTの設定
WebSocket もプロキシするようにリバースプロキシを設定する
デフォルトの設定では、Vite の前のリバースプロキシが WebSocket のプロキシに対応していることが期待されています。Vite の HMR クライアントが WebSocket の接続に失敗した場合、クライアントはリバースプロキシを迂回して直接 Vite の HMR サーバーに接続するようにフォールバックします:
Direct websocket connection fallback. Check out https://vite.dev/config/server-options.html#server-hmr to remove the previous connection error.
フォールバックが発生した際のブラウザーに表示されるエラーは無視できます。直接リバースプロキシを迂回してエラーを回避するには、次のいずれかを行えます:
WebSocket もプロキシするようにリバースプロキシを設定する
server.strictPort = true
を設定し、server.hmr.clientPort
をserver.port
と同じ値に設定する
server.hmr.port
をserver.port
とは異なる値に設定する
localhostのデフォルトが::1(IPv6) のシステムだとこのエラーが発生するらしく、hostを明示的に構成すればOKとある。
ということでconfig/vite.jsonのdevelopmentにhostを明示したらコンソールからエラーが消えた。
vite.config.tsでhostを指定しても変わらなかったのは、vite-plugin-railsでserver.hostをデフォルトでlocalhostにしており、上書きされてしまいvite.config.tsの設定が反映されなかったっぽい😭