You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Rails 6应用中加载自定义Gem内的JS文件

嘿,我完全懂你在从Rails 5切换到Rails 6时遇到的这个麻烦——之前用Sprockets能轻松加载自定义Gem里的JS,换成Webpacker之后就卡壳了,还不想靠yarn重新装一遍资源,就想直接用Gem里的原文件对吧?下面给你几个简洁的解决方案,不用搞一堆复杂的补丁或者额外文件:

方案1:把Gem的资源目录添加到Webpack的解析路径

Webpack需要明确知道去哪找这些Gem里的文件,所以我们可以修改config/webpack/environment.js,把Gem的JS资源目录添加到Webpack的解析路径中:

首先用bundle show [你的Gem名称]命令拿到Gem的安装绝对路径,比如我的Gem叫custom_ui_gem,执行后得到路径/Users/me/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/custom_ui_gem-1.2.3/app/assets/javascripts。

然后修改environment.js:

const { environment } = require('@rails/webpacker')
const path = require('path')

// 添加Gem的JS资源目录到Webpack的解析列表
environment.resolvedModules.prepend(
  path.resolve(__dirname, '../../../../.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/custom_ui_gem-1.2.3/app/assets/javascripts')
)
// 同时保留默认的node_modules路径
environment.resolvedModules.prepend('node_modules')

module.exports = environment

接下来调整app/javascript/packs/application.js的代码——注意普通JS文件不需要加.start(),只有Rails官方的模块(比如ujs、turbolinks)才需要调用初始化方法:

require("@rails/ujs").start()
require("turbolinks").start()
require("@rails/activestorage").start()
require("channels")

// 直接加载Gem里的JS文件
require('jquery-3.3.1.min')
require('popper.min')
require('bootstrap')
require('mdb')
require('wysiwyg')
require('addons/pickr.min')
require('modules/buttons')
require('modules/cards')
require('modules/waves')

方案2:用Webpack别名简化路径

如果觉得上面的绝对路径太长不好维护,可以给Gem的资源目录设置别名,修改environment.js:

const { environment } = require('@rails/webpacker')
const path = require('path')

environment.config.set('resolve.alias', {
  'gem-assets': path.resolve(__dirname, '../../../../.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/custom_ui_gem-1.2.3/app/assets/javascripts')
})

module.exports = environment

之后在application.js里就能用别名来引用文件了:

require('gem-assets/jquery-3.3.1.min')
require('gem-assets/addons/pickr.min')
// 其他文件同理

方案3:临时方案——复制Gem资源到项目目录

如果不想改Webpack配置,也可以把Gem里的JS文件直接复制到项目的app/javascript/vendor目录下:

# 先创建vendor目录(如果没有的话)
mkdir -p app/javascript/vendor
# 复制Gem里的所有JS文件
cp -r $(bundle show custom_ui_gem)/app/assets/javascripts/* app/javascript/vendor/

然后在application.js里引用:

require('vendor/jquery-3.3.1.min')
require('vendor/addons/pickr.min')

⚠️ 这个方法的缺点是Gem更新后需要手动重新复制资源,适合临时应急用。

额外注意事项

  • 如果遇到jQuery全局未定义的问题,可以在environment.js里配置Webpack的ProvidePlugin,让全局自动注入jQuery:
    const webpack = require('webpack')
    
    environment.plugins.prepend('Provide',
      new webpack.ProvidePlugin({
        $: 'jquery',
        jQuery: 'jquery'
      })
    )
    
  • 确认Gem里的文件路径完全正确,比如addons/pickr.min.js(注意是否有.js后缀,Webpack可能需要你补全,或者在配置里添加.js到扩展名解析列表)。

内容的提问来源于stack exchange,提问作者Rockwell Rice

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 06:23:41