使用jsbundling-rails(esbuild)替代Sprockets //= require:如何引入gem提供的JS代码?
Hey there, I totally get how frustrating it is to spend hours troubleshooting something that worked seamlessly with the old asset pipeline—let’s get this sorted out for you!
The key difference with jsbundling-rails is that it uses modern JS bundlers (like esbuild, webpack, or Rollup) instead of Sprockets, so we need to tell your bundler where to find the gem’s JS files. Here’s how to do it for the most common setups:
First: Locate the Gem’s JS Files
First, find exactly where your gem stores its JavaScript. Run this command in your terminal:
bundle show [your-gem-name]
This will output the full path to the gem’s installation directory. Navigate there and look for JS files—they’re usually in vendor/assets/javascripts/ or app/assets/javascripts/ inside the gem folder. Note this path down; we’ll need it later.
If You’re Using esbuild (jsbundling-rails Default)
Esbuild is the default bundler for jsbundling-rails, so this is the most likely scenario.
Option 1: Add the Gem Path to Your Build Command
Update the build script in your package.json to include the gem’s JS directory as a resolve path:
"scripts": { "build": "esbuild app/javascript/application.js --bundle --outfile=app/assets/builds/application.js --paths=$(bundle show [your-gem-name])/vendor/assets/javascripts" }
Then, in your app/javascript/application.js, you can import the gem’s JS directly:
import '[gem-js-filename]'
(Replace [gem-js-filename] with the actual JS file name from the gem, e.g., my-gem.js)
Option 2: Use a Config File for More Control
If you prefer a dedicated config file (create esbuild.config.js in your project root), you can define the path there:
const path = require('path'); const gemJsPath = path.join(__dirname, '../', (require('child_process').execSync('bundle show [your-gem-name]').toString().trim()), '/vendor/assets/javascripts'); require('esbuild').build({ entryPoints: ['app/javascript/application.js'], bundle: true, outfile: 'app/assets/builds/application.js', paths: { '*': [gemJsPath, 'app/javascript/*'] }, // Add any other esbuild options you need }).catch(() => process.exit(1));
Then update your package.json script to use this config:
"scripts": { "build": "node esbuild.config.js" }
If You’re Using Webpack
For webpack, you’ll need to add the gem’s JS path to your webpack.config.js so webpack can resolve imports:
const path = require('path'); const gemJsPath = path.join(__dirname, '../', (require('child_process').execSync('bundle show [your-gem-name]').toString().trim()), '/vendor/assets/javascripts'); module.exports = { // ... your existing webpack config resolve: { modules: [ gemJsPath, 'app/javascript', 'node_modules' ], // Alternatively, use an alias for a specific file: alias: { '[your-gem]': path.join(gemJsPath, '[gem-js-filename].js') } } };
Then import the gem in application.js like this:
import '[your-gem]'; // Or if you didn't use an alias: import '[gem-js-filename]';
Quick Troubleshooting Tips
- If the gem uses old-style IIFE/global JS: If the gem’s JS isn’t modular (it attaches to
windowinstead of usingexport), you can still import it—just useimport '[gem-js-filename]'and the bundler will include it in your build, making the global available. - Always rebuild after changes: Run
yarn build(ornpm run build) after modifying your config, and restart your Rails server to pick up the updated assets. - Double-check the path: It’s easy to mistype the gem’s JS directory—double-check that the path you’re pointing to actually contains the JS file you need.
内容的提问来源于stack exchange,提问作者smatysiak

