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

Rails从Sprockets迁移至Webpacker后依赖包加载异常求助

Fixing Global Dependency Issues When Migrating from Sprockets to Webpacker in Rails

Hey there! Let’s break down why you’re hitting these errors and get your dependencies working smoothly without manual includes.

Why This Is Happening

The core issue boils down to how Sprockets and Webpack handle JavaScript scope:

  • Sprockets loads all scripts into the global window scope by default. Any library you include is available everywhere on the page, just like you’re used to.
  • Webpack (the engine behind Webpacker) uses module-level scope out of the box. When you require() a library like d3 or shortcut.js, it’s only accessible inside that specific module file—not on the global window object.

Your errors (like Uncaught ReferenceError: shortcut is not defined and the datamaps warning) pop up because scripts like datamaps.usa.min.js and your inline code are searching for these libraries on the global window, but Webpack hasn’t exposed them there.

Solution 1: Manually Attach Libraries to the Global Window

The fastest fix is to explicitly assign your required libraries to window in your pack file. Update app/javascript/packs/client_application.js to this:

// Attach libraries to window so they're globally accessible
window.$ = window.jQuery = require("jquery");
window.shortcut = require("shortcut.js/shortcut");
window.d3 = require("d3/d3.min");
window.topojson = require("topojson");

// d3-tip can stay as-is if it attaches itself to the global d3 object
require("js/d3_tip");

This makes $, jQuery, shortcut, d3, and topojson available globally—just like they were with Sprockets. You can then delete all the javascript_include_tag lines from your client.haml and only keep = javascript_pack_tag "client_application".

Solution 2: Use Webpack's ProvidePlugin (More Elegant)

For a cleaner, scalable approach, use Webpack’s ProvidePlugin. This tool automatically injects libraries into every module that references them, and also makes them available globally for older scripts that expect window-scoped variables.

  1. Open config/webpack/environment.js.
  2. Add this configuration:
const { environment } = require('@rails/webpacker');
const webpack = require('webpack');

// Inject global dependencies automatically
environment.plugins.prepend('Provide',
  new webpack.ProvidePlugin({
    $: 'jquery',
    jQuery: 'jquery',
    d3: 'd3/d3.min',
    topojson: 'topojson',
    shortcut: 'shortcut.js/shortcut'
  })
);

module.exports = environment;
  1. Restart your Webpack dev server (bin/webpack-dev-server) to apply the changes.

With this setup, you can even remove the require() lines from your pack file if you don’t need them explicitly—Webpack will automatically include the libraries wherever they’re referenced (in your code or third-party scripts like datamaps).

Final Checks

  • Restart your Rails server and Webpack dev server to ensure all changes take effect.
  • Remove the manual javascript_include_tag lines from client.haml and test your app—your dependencies should now load correctly from the pack file alone.

内容的提问来源于stack exchange,提问作者Antarr Byrd

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 11:47:37