在 rails 7 项目中,若需引入无 es 模块结构、仅依赖全局变量的第三方 minified js 库(如 jquery 插件、旧版 chart.js 等),应绕过 importmap,转而使用 sprockets 的传统资产管线,通过 //= require 指令原样加载并合并脚本。
Rails 7 默认启用 importmap-rails,但其本质是将脚本包装为 ESM 模块——这对非模块化库(如直接挂载 window.Chart 或定义全局函数的脚本)极易导致运行时错误(如 ReferenceError: Chart is not defined)。此时,Sprockets 并未被弃用,而是作为兼容性极佳的“兜底方案”继续有效支持传统脚本管理。
创建标准目录结构
将第三方 JS 文件统一存放于 vendor/javascripts/(非 app/assets/javascripts/,避免与新式 JS 资源混淆):
mkdir -p vendor/javascripts cp ~/Downloads/chart.min.js vendor/javascripts/ cp ~/Downloads/moment.min.js vendor/javascripts/
配置 Sprockets 加载路径
在 config/initializers/assets.rb 中添加自定义路径:
# config/initializers/assets.rb
Rails.application.config.assets.paths << Rails.root.join("vendor/javascripts")声明主入口文件
创建 app/assets/javascripts/application_legacy.js(命名任意,但建议语义化),使用 Sprockets 指令按需引入:
// app/assets/javascripts/application_legacy.js
//= require_self
//= require_directory ../../../vendor/javascripts
// 可在此追加初始化代码(确保依赖已加载)
document.addEventListener("DOMContentLoaded", () => {
if (typeof Chart !== "undefined") {
new Chart(document.getElementById("myChart"), { /* config */ });
}
});注册到资产清单
编辑 app/assets/config/manifest.js,显式声明该文件为可预编译资源:
//= link application_legacy.js
在布局中引用
在 app/views/layouts/application.html.erb 中插入:
<%= javascript_include_tag "application_legacy", "data-turbo-track": "reload" %>
✅ 优势说明: ✅ 零修改原始库:Sprockets 以纯文本方式拼接 JS,不解析、不包装、不转换; ✅ 自动合并压缩:生产环境 rails assets:precompile 会将所有 //= require 文件合并为单个 application_legacy.js,并自动启用 Uglifier/Terser 压缩; ✅ 支持依赖顺序:通过 //= require xxx 显式控制加载顺序(如先 moment.min.js 后 chart.min.js); ✅ 开发体验友好:修改 vendor/javascripts/ 中任一文件,刷新页面即可生效(无需重启服务器)。

此方案兼顾 Rails 7 新架构的现代性与遗留库的兼容性,是官方文档明确支持的“混合资产策略”,无需 hack public/ 目录或手动维护