This guide provides step-by-step instructions to migration from Webpacker 5
to jsbundling-rails
with webpack 5
. For upgrading to Webpacker 6 instead, follow this guide or for comparison between Webpacker and jsbundling-rails, see this.
First install jsbundling-rails
:
# Add to your Gemfile
+ gem 'jsbundling-rails'
# From the CLI, rebuild the bundle
./bin/bundle install
# From the CLI, create a baseline configuration
./bin/rails javascript:install:webpack
The installation script will:
- Add builds to the manifest
- Ignore builds from git
- Setup
foreman
for running multiple processes - Create
./webpack.config.js
- Add the build script to
package.json
If you would like to minimize the diff between Webpacker and jsbundling-rails:
- Move
./webpack.config.js
into./config/webpack/
- Change the config path in
package.json
- "build": "webpack --config ./webpack.config.js"
+ "build": "webpack --config ./config/webpack/webpack.config.js"
- Change the output path in
webpack.config.js
- path: path.resolve(__dirname, "app/assets/builds"),
+ path: path.resolve(__dirname, '..', '..', 'app/assets/builds')
- Delete the following files
./bin/webpack
./bin/webpack-dev-server
./config/initializers/webpacker.rb
./config/webpacker.yml
./config/webpack/development.js
./config/webpack/environment.js
./config/webpack/production.js
./config/webpack/test.js
- Remove Webpacker gem
# Remove from your Gemfile
- gem 'webpacker'
- Run
./bin/bundle install
Webpacker includes many dependencies by default while jsbundling-rails leaves it to you. If you're only handling JavaScript with no modifications you'll only need to install webpack-cli
. Treat the rest of this section ala-carte.
# From the CLI, add webpack-cli
yarn add webpack-cli
# Then remove Webpacker packages
yarn remove @rails/webpacker webpack-dev-server
Babel is used to transpile source code to earlier versions of JavaScript.
- Install packages
# From the CLI, add babel presets
yarn add @babel/core @babel/preset-env
- Configure Babel
// In package.json, add
+ "babel": {
+ "presets": ["@babel/env"]
+ }
- Use the loader in webpack
// in webpack.config.js, add
module.exports = {
module: {
rules: [
+ {
+ test: /\.(js)$/,
+ exclude: /node_modules/,
+ use: ['babel-loader'],
+ },
],
},
};
You can use Babel to transpile front-end frameworks and TypeScript. This example setup uses React with TypeScript.
- Install packages
# From the CLI, add babel presets
yarn add @babel/core @babel/preset-env @babel/react @babel/preset-typescript
- Configure Babel
// In package.json, add
+ "babel": {
+ "presets": [
+ "@babel/env",
+ "@babel/react",
+ "@babel/preset-typescript"
+ ]
+ }
- Configure webpack
// in webpack.config.js, add
module.exports = {
module: {
rules: [
+ {
+ test: /\.(js|jsx|ts|tsx|)$/,
+ exclude: /node_modules/,
+ use: ['babel-loader'],
+ },
],
},
};
With the right loaders, webpack can handle CSS files. This setup only uses jsbundling-rails, excluding cssbundling-rails from handling files.
- Install packages
# From the CLI, add loaders, plugins, and node sass
yarn add css-loader sass sass-loader mini-css-extract-plugin webpack-fix-style-only-entries
- Configure webpack
// In webpack.config.js
// Extracts CSS into .css file
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
// Removes exported JavaScript files from CSS-only entries
// in this example, entry.custom will create a corresponding empty custom.js file
const RemoveEmptyScriptsPlugin = require('webpack-remove-empty-scripts');
module.exports = {
entry: {
// add your css or sass entries
application: [
'./app/assets/javascripts/application.js',
'./app/assets/stylesheets/application.scss',
],
custom: './app/assets/stylesheets/custom.scss',
},
module: {
rules: [
// Add CSS/SASS/SCSS rule with loaders
{
test: /\.s[ac]ss$/i,
use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'],
},
],
},
resolve: {
// Add additional file types
extensions: ['.js', '.jsx', '.scss', '.css'],
},
plugins: [
// Include plugins
new RemoveEmptyScriptsPlugin(),
new MiniCssExtractPlugin(),
],
};
Webpack can handle other files. This setup may vary on your use, but will look something like this:
- Configure webpack
// in webpack.config.js, add
module.exports = {
module: {
rules: [
+ {
+ test: /\.(jpe?g|svg|png|gif|ico|eot|ttf|woff2?)(\?v=\d+\.\d+\.\d+)?$/i,
+ type: 'asset/resource',
+ },
],
},
};
Confirm you have a working webpack configuration. You can rebuild the bundle with:
yarn build --progress --color
If you have multiple entries, it's recommended to confirm one at a time, and finally the entire bundle.
Find + replace uses of Webpacker
's asset tags.
# Webpacker tag # Sprockets tag
javascript_pack_tag = javascript_include_tag
stylesheet_pack_tag = stylesheet_link_tag
Once the tags are replaced your app should be working same as before!
jsbundling-rails
ships with only production
mode. You can dramatically speed up build times during development by switching to mode: 'development'
.
// Make the following changes in webpack.config.js
+ const mode = process.env.NODE_ENV === 'development' ? 'development' : 'production';
module.exports = {
- mode: "production",
+ mode,
- devtool: "source-map",
…
+ optimization: {
+ moduleIds: 'hashed',
+ }
}
Webpack builds with can be slower, one way to improve the speed is offload some load to esbuild using esbuild-loader
{
test: /\.(js)$/,
exclude: /node_modules/,
+ use: ['esbuild-loader'],
- use: ['esbuild-loader'],
},
optimization: {
moduleIds: 'deterministic',
minimize: true,
minimizer: [
new ESBuildMinifyPlugin({
target: 'es2015',
css: true,
})],
},