如何让Rails加载编译后的application.js而非源文件?
核心原因
生产环境中Rails的Sprockets资产管道会自动处理/app/javascript目录下的文件,执行assets:precompile时会把原文件复制到/app/assets/javascripts,直接覆盖你用esbuild编译好的文件。
解决步骤
调整esbuild输出目录,避开资产管道冲突
不要把编译后的文件输出到/app/assets/javascripts,这个目录是Sprockets的默认处理目录,很容易被覆盖。建议改成/public/assets/javascripts或者直接/public/javascripts。修改package.json里的脚本命令:"scripts": { "build": "esbuild app/javascript/application.js --bundle --minify --sourcemap --outfile=public/assets/javascripts/application.js", "watch": "esbuild app/javascript/application.js --bundle --watch --sourcemap --outfile=public/assets/javascripts/application.js" }修改JS引入标签
编译后的文件已经是打包好的非模块JS,不需要type: :module属性,同时确保路径正确:<%= javascript_include_tag "application", media: :all, defer: true %>固定部署流程顺序
部署时必须先执行esbuild编译,再跑Rails的资产预编译。比如在CI/CD脚本、Capistrano任务或者Dockerfile里,先执行npm run build,再执行rails assets:precompile。如果用Heroku这类平台,默认会优先执行npm的build命令,确保package.json里的build命令配置正确即可。(可选)强制排除原JS文件被Sprockets处理
如果坚持要把输出放在/app/assets/javascripts,需要修改config/initializers/assets.rb,让Sprockets忽略原/app/javascript目录:Rails.application.config.assets.excluded_paths << Rails.root.join('app/javascript') Rails.application.config.assets.precompile += %w( application.js )这种方式不如调整输出目录稳妥,不优先推荐。
内容的提问来源于stack exchange,提问作者Some Guy

