Rails7+Puma+Nginx生产环境JS资源加载失败求助
问题描述
使用 Rails 7 + Ruby 3 + Puma + Nginx 部署生产服务器后,JS 资源加载失败,服务器日志显示无法找到 main.js、bootstrap.bundle.min.js、owl.carousel.min.js 等文件。项目中 JS 文件分布如下:
app/assets/js:active_admin.js、application.js、owl.carousel.min.jsapp/javascripts:application.js及controllers子目录文件
已尝试执行 assets:clobber、assets:precompile 命令,并设置 config.serve_static_files = true 和 config.serve_static_assets = true,但问题未解决。生产环境关键日志如下:
I, [2023-09-25T09:20:41.408520 #261785] INFO -- : [feda6a42-adfa-443f-a4ef-541d7d55b836] Started GET "/services/js/bootstrap.bundle.min.js" for 127.0.0.1 at 2023-09-25 09:20:41 +0000 I, [2023-09-25T09:20:41.411611 #261785] INFO -- : [962b6dd3-4fdf-485c-b706-881990a91d0a] Started GET "/services/lib/owlcarousel/owl.carousel.min.js" for 127.0.0.1 at 2023-09-25 09:20:41 +0000 F, [2023-09-25T09:20:41.417244 #261785] FATAL -- : [962b6dd3-4fdf-485c-b706-881990a91d0a] [962b6dd3-4fdf-485c-b706-881990a91d0a] ActionController::RoutingError (No route matches [GET] "/services/lib/owlcarousel/owl.carousel.min.js"):
问题分析
从日志可见,浏览器请求的 JS 路径为 /services/js/xxx.js,这是相对路径解析错误导致的:当前页面路径是 /services/new,相对路径会被浏览器解析为相对于该页面的路径,而非 Rails 资产管道的标准路径 /assets/xxx.js。此外,可能存在资产预编译配置不全、Nginx 静态资源路由未正确配置的问题。
解决方案
1. 修正视图中的 JS 引用方式
替换视图中硬编码的相对路径引用,改用 Rails 官方资产辅助方法:
- 若使用资产管道(Sprockets):
<%# 在 layouts/application.html.erb 或对应视图中 %> <%= javascript_include_tag 'main' %> <%= javascript_include_tag 'bootstrap.bundle.min' %> <%= javascript_include_tag 'owl.carousel.min' %> - 若使用 Rails 7 默认的 Importmap:
- 在
config/importmap.rb中 pin 目标文件:pin "main", to: "js/main.js" pin "bootstrap.bundle.min", to: "js/bootstrap.bundle.min.js" pin "owl.carousel.min", to: "js/owl.carousel.min.js" - 在
app/javascript/application.js中导入:import "main" import "bootstrap.bundle.min" import "owl.carousel.min"
- 在
2. 完善资产预编译配置
- 编辑
config/environments/production.rb,确保以下配置正确(Rails 5+ 用public_file_server.enabled替代旧配置):config.public_file_server.enabled = true config.assets.compile = false # 生产环境禁用实时编译,确保预编译所有资产 config.assets.digest = true # 启用指纹缓存,避免浏览器缓存旧资源 - 编辑
config/initializers/assets.rb,添加需要预编译的 JS 文件:Rails.application.config.assets.precompile += %w( main.js bootstrap.bundle.min.js owl.carousel.min.js )
3. 重新预编译并部署资产
执行以下命令清理旧资产、重新预编译:
rails assets:clobber RAILS_ENV=production rails assets:precompile
确认预编译后的文件生成在 public/assets 目录下,文件名带指纹(如 main-abc123.js)。
4. 检查 Nginx 配置
确保 Nginx 直接处理 /assets 路径的请求,不转发给 Puma:
server { # 其他配置... # 直接由 Nginx 提供静态资产 location ~ ^/assets/ { expires 1y; add_header Cache-Control public; add_header ETag ""; break; } # 转发动态请求到 Puma location / { proxy_pass http://localhost:3000; # 替换为你的 Puma 监听地址 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; } }
修改后重启 Nginx:sudo systemctl restart nginx
内容的提问来源于stack exchange,提问作者Azhar Sheikh
相关产品推荐
相关产品推荐

