Rails 7.0.x/Ruby3.1.2如何配置使用gzip预压缩JS静态资源
问题根因
Sprockets(Rails默认资产管道)的//= require指令仅支持引入可被解析的JS/CSS源文件,.js.gz是gzip压缩后的二进制产物,不属于可被合并解析的JavaScript源码,直接引用必然触发文件类型不匹配、找不到文件的报错。
你提前用compression-webpack-plugin生成的gz文件不需要合并到JS文件内部——gzip是HTTP传输层的编码优化,作用是减少资源传输体积,正确的逻辑是:资产预编译阶段同时保留未压缩的JS源文件和对应的gz预压缩文件,部署后由Web服务器自动判断客户端支持情况,优先返回gz文件。
配置步骤
- 修正JS引入逻辑
打开app/assets/javascripts/application.js,删除原来错误的gz文件引用,改为引入webpack生成的未压缩JS源文件,不需要加后缀://= require vendor-bundle //= require app-bundle - 修正
config/initializers/assets.rb配置
首先修复原配置里的语法错误(原配置多写了一个右括号,且错误嵌套了数组),再添加预编译规则、关闭Sprockets自带的重复gzip压缩逻辑:# 注册webpack输出的资产路径 Rails.application.config.assets.paths << Rails.root.join('app', 'assets', 'webpack') # 配置需要预编译的资源列表,修复原配置的语法错误 Rails.application.config.assets.precompile += %w[ application.js fullWidthContainer.js IEAlertScript.js carousel.js # 纳入所有webpack预生成的gz压缩文件 *.js.gz ] # 关闭Sprockets自带的gzip压缩功能,避免重复生成压缩文件,直接使用webpack生成的高压缩率gz包 config.assets.gzip = false - 确认生产环境配置
你现有的config/environments/production.rb配置不需要大改,保持以下配置即可:
如果你的webpack已经对vendor-bundle、app-bundle做过terser压缩,可以把config.assets.js_compressor = :terser config.assets.css_compressor = :sass # 保持关闭实时编译,避免生产环境性能问题 config.assets.compile = falseconfig.assets.js_compressor临时注释掉跑一次预编译对比,没有出现语法问题的话可以关闭,加快预编译速度。 - 配置Web服务器开启静态gzip返回
这一步是生效的关键:预编译完成后,public/assets目录下会同时存在未压缩的.js文件和对应的.js.gz文件,你需要给前端Web服务器开启gzip静态资源匹配规则,比如Nginx添加gzip_static on;配置,Caddy默认支持gzip静态文件,开启后当客户端请求JS资源时,服务器会自动检测同路径下的gz文件,给支持gzip编码的客户端直接返回压缩后的2MB文件,不需要实时压缩,既省服务器性能又能达到减小传输体积的目的。
注意事项
- 不要尝试把gz文件的二进制内容直接合并到JS源码里,会直接导致JS语法错误,页面功能完全失效。
- 执行
rails assets:precompile后,记得去public/assets目录检查,确认未压缩的JS文件和对应的gz文件都存在,避免不支持gzip的老旧客户端无法加载资源。 - 确认webpack的输出路径是你配置的
app/assets/webpack目录,且输出的vendor-bundle.js、app-bundle.js文件名和require里的名称对应,不要出现文件名加了随机hash但Sprockets找不到的情况。
内容的提问来源于stack exchange,提问作者Kunal Vashist
相关产品推荐
相关产品推荐

