无需重建Docker容器,用Webpacker(webpack-dev-server)在容器内编译
解决Rails 4.2 + Webpacker + Docker(OSX)的热重载问题
我之前在OSX上用Docker跑混合Sprockets/Webpacker的Rails项目时,也碰到过一模一样的热重载坑,结合你给出的环境(Docker 17.12.0-ce、OSX High Sierra 10.12.6、Rails 4.2),给你整理几个关键的修复步骤,亲测有效:
1. 修复文件监听失效问题(OSX Docker核心痛点)
OSX上Docker的文件系统挂载不支持高效的inotify机制,Webpack默认的监听模式根本检测不到宿主机的文件变化。解决办法是让Webpack主动轮询文件:
- 修改
config/webpacker.yml,在development区块里添加:development: # 其他配置... watch_options: poll: 1000 # 每秒轮询一次,数值可根据你的机器性能调整
2. 正确配置Webpack Dev Server的网络与端口
Docker容器内的服务默认只能本地访问,必须把Webpack Dev Server的端口映射到宿主机,同时允许外部访问:
- 更新你的
docker-compose.yml:services: web: build: . command: bundle exec rails s -b 0.0.0.0 environment: - RAILS_ENV=development - WEBPACKER_DEV_SERVER_HOST=0.0.0.0 # 允许容器外部访问Dev Server - WEBPACKER_DEV_SERVER_PORT=3035 ports: - "3000:3000" # Rails应用端口 - "3035:3035" # Webpack Dev Server端口 volumes: - .:/app:cached # 用cached挂载提升OSX上的文件读写性能(Docker 17.06+支持) - 然后在
config/environments/development.rb里指定Webpack Dev Server的地址:Rails.application.configure do # 其他配置... config.webpacker.dev_server.host = ENV['WEBPACKER_DEV_SERVER_HOST'] || 'localhost' config.webpacker.dev_server.port = ENV['WEBPACKER_DEV_SERVER_PORT'] || 3035 end
3. 确保React组件的热重载逻辑生效
如果你的React组件没有自动刷新,可能是缺少热重载的入口代码:
- 在
app/javascript/packs/application.js末尾添加:
这会告诉Webpack在模块变化时接受更新,无需刷新整个页面(如果是单个组件,也可以针对特定模块添加if (module.hot) { module.hot.accept(); }module.hot.accept('./MyComponent', () => { ... }))。
4. 解决容器内的文件权限问题
OSX上Docker容器的用户ID和宿主机不一致,可能导致Webpack无法写入编译文件:
- 在
docker-compose.yml里添加用户ID配置:services: web: # 其他配置... user: "${UID:-1000}:${GID:-1000}" - 启动容器时带上当前用户的ID:
UID=$(id -u) GID=$(id -g) docker-compose up
5. 验证配置是否生效
- 启动容器后,访问
http://localhost:3035,如果能看到Webpack Dev Server的状态页面,说明服务正常运行。 - 修改任意React组件文件,查看容器日志,如果看到
webpack compiled successfully的提示,同时浏览器自动刷新,就说明热重载已经正常工作了!
内容的提问来源于stack exchange,提问作者MattLock
相关产品推荐
相关产品推荐

