如何在Rails 8.0.1中使用Propshaft合并多个静态JavaScript文件为单个文件?
嘿,我完全懂你的需求——就是想要像以前用Sprockets时那样,不用折腾模块或者Importmaps,直接把一堆静态JS文件合并成一个application.js对吧?Propshaft虽然和Sprockets的逻辑不太一样,但也能轻松实现这个效果,我给你一步步说清楚:
核心思路:用ES导入语句聚合文件
Propshaft本身不支持Sprockets那种//= require_tree .的指令,但我们可以用原生的ES import语句来实现类似的合并效果,操作起来很简单:
确认资产目录配置
先检查config/assets/config/manifest.js,确保它包含了你的JavaScript目录,这样Propshaft能识别所有JS文件://= link_tree ../images //= link_tree ../javascripts .js //= link_tree ../stylesheets .css创建入口文件并导入所有静态JS
在app/assets/javascripts/application.js里,用import语句引入所有你需要合并的JS文件。比如你的文件都在当前目录下,就像这样:// app/assets/javascripts/application.js // 按你需要的执行顺序导入文件 import './utils.js'; import './form-helpers.js'; import './carousel.js'; // ... 依次导入所有其他静态JS文件这样Propshaft在处理资产时,会把这些导入的文件按顺序合并到
application.js里。在页面中引用入口文件
在你的布局文件(比如app/views/layouts/application.html.erb)里,添加对application.js的引用:<%= javascript_include_tag "application", defer: true %>生产环境预编译
当你在生产环境运行rails assets:precompile时,Propshaft会自动把所有导入的JS文件合并成一个带指纹的application-[哈希值].js文件,和以前Sprockets的效果完全一致,还能自动压缩(如果你配置了压缩器的话)。
进阶技巧:自动生成导入语句(替代require_tree)
如果你有几十上百个JS文件,手动写import太麻烦,可以用一个简单的Ruby脚本自动生成导入语句:
# 在项目根目录创建generate_imports.rb require 'pathname' js_dir = Pathname.new(File.join(__dir__, 'app/assets/javascripts')) # 排除application.js本身 js_files = Dir.glob("#{js_dir}/**/*.js").reject { |f| f.end_with?('application.js') } imports = js_files.map do |file| relative_path = Pathname.new(file).relative_path_from(js_dir).to_s.gsub(/\.js$/, '') "import './#{relative_path}';" end # 写入application.js File.write(js_dir.join('application.js'), imports.join("\n"))
运行这个脚本:ruby generate_imports.rb,它就会自动把所有静态JS文件的导入语句写入application.js,完美替代Sprockets的//= require_tree .!
注意事项
- 如果你不需要模块作用域,确保你的静态JS文件都是全局变量/函数的形式,这样合并后不会有作用域冲突的问题。
- 可以在
config/environments/production.rb里配置JS压缩,让合并后的文件更小:config.assets.js_compressor = :terser
这样操作下来,你就能轻松实现和之前Sprockets一样的静态JS合并效果啦,完全不用碰复杂的模块系统~
备注:内容来源于stack exchange,提问作者Tintin81

