在 rails 7 中,当需引入无 es 模块封装、仅依赖全局变量的第三方 minified js 库(如传统 jquery 插件)时,应绕过 importmap,改用 sprockets 的 require 指令机制,将其集中托管于 `vendor/javascripts` 并自动打包进单一资产文件。
Rails 7 默认启用 Importmap 作为现代 JS 依赖管理方案,但它要求所有被 import 的脚本必须符合 ESM 规范(或至少是可执行的 IIFE)。而大量遗留库(如 Chart.js v2、Select2 v3、旧版 Lightbox 等)以立即执行函数或全局变量形式(如 window.Chart)发布,直接通过 importmap-rails 引入会导致 ReferenceError 或 undefined is not a function —— 因为 Importmap 会强制包裹脚本、隔离作用域,破坏其全局暴露逻辑。
此时,Sprockets(Rails 资产管道的经典引擎)仍是可靠选择。它不修改源码、不注入包装器,仅按顺序拼接并提供预编译能力,完美适配非模块化脚本。
创建标准目录结构
将所有第三方 minified JS 文件统一存放至 vendor/javascripts/(非 app/assets/javascripts/,避免与 Stimulus/ESM 混淆):
mkdir -p vendor/javascripts cp ~/Downloads/chart.min.js vendor/javascripts/ cp ~/Downloads/select2.min.js vendor/javascripts/
注册路径并配置清单
在 config/initializers/assets.rb 中添加自定义路径:
Rails.application.config.assets.paths << Rails.root.join("vendor/javascripts")在 app/assets/config/manifest.js 中声明主入口文件:
//= link do_not_name_me_application.js
编写聚合入口文件
创建 app/assets/javascripts/do_not_name_me_application.js(文件名可自定义,但需与 manifest 中一致),使用 Sprockets 指令加载全部第三方脚本:
//= require_directory ../../../vendor/javascripts //= require_tree. // 可在此追加初始化代码(确保依赖已就绪) document.addEventListener("DOMContentLoaded", () => { if (typeof Chart !== "undefined") { console.log("Chart.js loaded globally ✅"); } });
在布局中引入
替换掉 (若你已停用 Importmap 的 application.js),改为:
<%= javascript_include_tag "do_not_name_me_application", "data-turbo-track": "reload" %>
启动服务器后访问:
http://localhost:3000/assets/do_not_name_me_application.js
应返回完整拼接后的 JS 内容(含原始 minified 代码 + 初始化逻辑),无语法错误,且浏览器控制台可调用 Chart, $, jQuery 等全局变量。
此方式兼顾简洁性、可维护性与 Rails 原生资产流程,是 Rails 7 中集成传统 JS 库的标准、稳定、可扩展方案。