Migrate from Webpacker to jsbundling-rails
masterjsbundling-rails using Webpack (or another bundler). You can follow the official switching guide provided by the jsbundling-rails repository to transition your application.repository·master·Indexed 26 days ago
https://github.com/rails/webpackerA retired bridge for compiled and bundled JavaScript in Rails using webpack. This documentation covers version 6.0.0-rc.6, including Babel configuration for React, deployment to Heroku and Nginx, Capistrano integration, and troubleshooting guides. It also provides migration paths to jsbundling-rails, importmap-rails, or the community-driven Shakapacker.
jsbundling-rails using Webpack (or another bundler). You can follow the official switching guide provided by the jsbundling-rails repository to transition your application.To serve precompressed Brotli files (.br) in Nginx, you must install the ngx_brotli module. Once installed, load the static module in your nginx.conf file:
load_module modules/ngx_http_brotli_static_module.so;Then, enable it in your site configuration using brotli_static on; within the assets/packs location block.
To run a Webpacker app on Heroku, you must add both the Node.js and Ruby buildpacks. This ensures that npm or yarn executables are available to compile your assets during the deployment process.
Follow these steps:
heroku/nodejs buildpack.heroku/ruby buildpack.heroku create my-webpacker-heroku-app
heroku addons:create heroku-postgresql:hobby-dev
heroku buildpacks:add heroku/nodejs
heroku buildpacks:add heroku/ruby
git push heroku masterTo debug your Webpack configuration, you can use the following methods:
debugger statement in your Webpack configuration and run bin/webpacker --debug-webpacker. You can use the Chrome debugger by navigating to chrome://inspect or using the NiM extension.bin/webpacker are forwarded to Webpack. For example, use --debug to switch loaders to debug mode.bin/webpacker --debug-webpacker.bin/webpacker --debug-webpackerconfig.action_controller.asset_host setting. If your Rails application is already configured to use a CDN via this setting, Webpacker will automatically use it without additional configuration.Webpacker does not serve files in production; you must configure your web server (like Nginx) to serve files directly from the public/ directory.
To optimize performance, you can use gzip_static to serve precompressed .gz files and brotli_static to serve .br files. Ensure your Nginx configuration includes a location block for assets and packs that sets appropriate cache headers and enables static compression.
upstream app {
# server unix:///path/to/app/tmp/puma.sock;
}
server {
listen 80;
server_name www.example.com;
root /path/to/app/public;
location @app {
proxy_pass http://app;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location / {
try_files $uri @app;
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
location ~ /\.(?!well-known).* {
deny all;
}
location ~ ^/(assets|packs)/ {
gzip_static on;
brotli_static on; # Optional
expires max;
add_header Cache-Control public;
}
}To prevent assets from recompiling on every deployment when files haven't changed, add public/packs and node_modules to your :linked_dirs in Capistrano.
If you add node_modules to :linked_dirs, you must ensure yarn install runs before deploy:assets:precompile by adding a custom task to your deploy.rb.
# In deploy.rb
append :linked_dirs, "log", "tmp/pids", "tmp/cache", "tmp/sockets", "public/packs", ".bundle", "node_modules"
before "deploy:assets:precompile", "deploy:yarn_install"
namespace :deploy do
desc "Run rake yarn install"
task :yarn_install do
on roles(:web) do
within release_path do
execute("cd #{release_path} && yarn install --silent --no-progress --no-audit --no-optional")
end
end
end
endTo silence Angular-related critical dependency warnings in Webpack, update your config/webpack/base.js to include a ContextReplacementPlugin.
const webpack = require('webpack')
const { resolve } = require('path')
const { webpackConfig, merge } = require('@rails/webpacker')
module.exports = merge(webpackConfig, {
plugins: [
new webpack.ContextReplacementPlugin(
/angular(\\|\/)core(\\|\/)(@angular|esm5)/,
resolve(config.source_path)
)
]
})To use React with Webpacker, you must install the necessary dependencies and configure babel.config.js to include @babel/preset-react and optional plugins like react-refresh for development.
yarn add react react-dom @babel/preset-react
yarn add --dev @pmmmwh/react-refresh-webpack-plugin react-refreshbabel.config.js to merge the React preset and development plugins into the Webpacker default config.// babel.config.js
module.exports = function (api) {
const defaultConfigFunc = require('@rails/webpacker/package/babel/preset.js')
const resultConfig = defaultConfigFunc(api)
const isProductionEnv = api.env('production')
const changesOnDefault = {
presets: [
[
'@babel/preset-react',
{
development: isDevelopmentEnv || isTestEnv,
useBuiltIns: true
}
],
isProductionEnv && ['babel-plugin-transform-react-remove-prop-types',
{
removeImport: true
}
]
].filter(Boolean),
plugins: [
process.env.WEBPACK_SERVE && 'react-refresh/babel'
].filter(Boolean),
}
resultConfig.presets = [...resultConfig.presets, ...changesOnDefault.presets]
resultConfig.plugins = [...resultConfig.plugins, ...changesOnDefault.plugins ]
return resultConfig
}importmap-rails. This is the default setup for new Rails 7 applications, though the complexity of the migration depends on your specific JavaScript requirements.Instead of manually assigning dependencies to the window object (e.g., window.jQuery = jQuery), use Webpack's ProvidePlugin in config/webpack/base.js. This manages build-time dependencies to global symbols automatically.
// config/webpack/base.js
const webpack = require('webpack')
const { webpackConfig, merge } = require('@rails/webpacker')
module.exports = merge(webpackConfig, {
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
})
],
})