There are several substantial changes in Shakapacker v6 that you need to manually account for when coming from Webpacker 5. This guide will help you through it.
ShakaCode offers support for upgrading from webpacker or using Shakapacker. If interested, contact justin@shakacode.com.
By default, Webpacker 6 is focused on compiling and bundling JavaScript. This pairs with the existing asset pipeline in Rails that's setup to transpile CSS and static images using Sprockets. For most developers, that's the recommended combination. But if you'd like to use Webpacker for CSS and static assets as well, please see integrations for more information.
Webpacker used to configure Webpack indirectly, which lead to a complicated secondary configuration process. This was done in order to provide default configurations for the most popular frameworks, but ended up creating more complexity than it cured. So now Webpacker delegates all configuration directly to Webpack's default configuration setup. Additionally, all major dependencies, like webpack
and babel
are now peer dependencies, so you are free to upgrade those.
While you have to configure integration with frameworks yourself, webpack-merge
helps with this. See this example for Vue and scroll to the bottom for more examples.
See an example migration here: PR 27.
- Remove setting the NODE_ENV in your
bin/webpacker
andbin/webpacker-dev-server
bin stubs as these are not set in the webpack runner file.
If you're on webpacker v5, follow how to upgrade to webpacker v6.0.0.rc.6 from v5 to get to v6.0.0.rc.6 first.
- Change the gem name from
webpacker
toshakapacker
and the NPM package from@rails/webpacker
toshakapacker
. - Install the peer dependencies. Run
yarn add @babel/core @babel/plugin-transform-runtime @babel/preset-env @babel/runtime babel-loader compression-webpack-plugin terser-webpack-plugin webpack webpack-assets-manifest webpack-cli webpack-merge webpack-sources webpack-dev-server
. You may have old versions of libraries. Runyarn install
and check for warnings likewarning " > shakapacker@6.1.1" has incorrect peer dependency "compression-webpack-plugin@^9.0.0"
andfile-loader@1.1.11" has incorrect peer dependency "webpack@^2.0.0 || ^3.0.0 || ^4.0.0"
. In other words, warnings like these are serious and will cause considerable confusion if not respected. - Update any scripts that called
bin/webpack
orbin/webpack-dev-server
tobin/webpacker
orbin/webpacker-dev-server
- Update your webpack config for a single config file,
config/webpack/webpack.config.js
. If you want to use the prior style of having a separate file for each NODE_ENV, you can use this shim forconfig/webpack/webpack.config.js
. WARNING, previously, if you did not setNODE_ENV
,NODE_ENV
defaulted todevelopment
. Thus, you might expectconfig/webpack/development.js
to run, but you'll instead be using the the configuration file that corresponds to yourRAILS_ENV
. If yourRAILS_ENV
istest
, you'd be runningconfig/webpack/test.js
.
// name this file config/webpack/webpack.config.js
const { env, webpackConfig } = require('shakapacker')
const { existsSync } = require('fs')
const { resolve } = require('path')
const envSpecificConfig = () => {
const path = resolve(__dirname, `${env.nodeEnv}.js`)
if (existsSync(path)) {
console.log(`Loading ENV specific webpack configuration file ${path}`)
return require(path)
} else {
// Probably an error if the file for the NODE_ENV does not exist
throw new Error(`Got Error with NODE_ENV = ${env.nodeEnv}`);
}
}
module.exports = envSpecificConfig()
- Update
babel.config.js
if you need JSX support. See Customizing Babel Config
-
Ensure you have a clean working git branch. You will be overwriting all your files and reverting the changes that you don't want.
-
Ensure no nested directories in your
source_entry_path
. Check if you had any entry point files in child directories of yoursource_entry_path
. Files for entry points in child directories are not supported by shakacode/shakapacker v6. Move those files to the top level, adjusting any imports in those files.The v6 configuration does not allow nesting, so as to allow placing the entry points at in the root directory of JavaScript. You can find this change here.
-
Upgrade the Webpacker Ruby gem and the NPM package
Note: Check the gem page to verify the latest version, and make sure to install identical version numbers of
webpacker
gem and package.Example going to a specific version:
# Gemfile gem 'webpacker', '6.0.0.rc.6'
bundle install
yarn add @rails/webpacker@6.0.0-rc.6 --exact
bundle exec rails webpacker:install
Overwrite all files and check what changed.
Note, the webpacker:install will install the peer dependencies:
yarn add @babel/core @babel/plugin-transform-runtime @babel/preset-env @babel/runtime babel-loader compression-webpack-plugin terser-webpack-plugin webpack webpack-assets-manifest webpack-cli webpack-merge webpack-sources webpack-dev-server
-
Review the new default's changes to
webpacker.yml
. Consider each suggested change carefully, especially the change to have yoursource_entry_path
be at the top level of yoursource_path
. The v5 default usedpacks
forsource_entry_path
:source_path: app/javascript source_entry_path: packs
The v6 default uses the top level directory.
source_path: app/javascript source_entry_path: /
If you prefer this configuration, then you will move your
app/javascript/packs/*
(includingapplication.js
) toapp/javascript/
and update the configuration file.Note, moving your files is optional, as you can stil keep your entries in a separate directory, called something like
packs
, orentries
. This directory is defined with thesource_path
. -
Update
webpack-dev-server
to the current version, greater than 4.2, updatingpackage.json
. -
Update API usage of the view helpers by changing
javascript_packs_with_chunks_tag
andstylesheet_packs_with_chunks_tag
tojavascript_pack_tag
andstylesheet_pack_tag
. Ensure that your layouts and views will only have at most one call tojavascript_pack_tag
and at most one call tostylesheet_pack_tag
. You can now pass multiple bundles to these view helper methods. If you fail to changes this, you may experience performance issues, and other bugs related to multiple copies of React, like issue 2932. If you expose jquery globally withexpose-loader,
by usingimport $ from "expose-loader?exposes=$,jQuery!jquery"
in yourapp/javascript/application.js
, pass the optiondefer: false
to yourjavascript_pack_tag
. -
If you are using any integrations like
css
,postcss
,React
orTypeScript
. Please see https://github.com/shakacode/shakapacker#integrations section on how they work in v6. -
config/webpack/environment.js
was changed toconfig/webpack/base.js
and exports a native webpack config so no need to calltoWebpackConfig
. Usemerge
to make changes:// config/webpack/base.js const { webpackConfig, merge } = require('@rails/webpacker'); const customConfig = { module: { rules: [ { test: require.resolve('jquery'), loader: 'expose-loader', options: { exposes: ['$', 'jQuery'] } } ] } }; module.exports = merge(webpackConfig, customConfig);
-
Copy over custom browserlist config from
.browserslistrc
if it exists into the"browserslist"
key inpackage.json
and remove.browserslistrc
. -
Remove
babel.config.js
if you never changed it. Configure yourpackage.json
to use the default:"babel": { "presets": [ "./node_modules/@rails/webpacker/package/babel/preset.js" ] }
See customization example the Customizing Babel Config for React configuration.
-
extensions
was removed from thewebpacker.yml
file. Move custom extensions to your configuration by merging an object like this. For more details, see docs for Webpack Configuration{ resolve: { extensions: ['.ts', '.tsx', '.vue', '.css'] } }
-
In
webpacker.yml
, check if you hadwatched_paths
. That is nowadditional_paths
. -
Some dependencies were removed in PR 3056. If you see the error:
Error: Cannot find module 'babel-plugin-macros'
, or similar, then you need toyarn add <dependency>
where might include:babel-plugin-macros
,case-sensitive-paths-webpack-plugin
,core-js
,regenerator-runtime
. Or you might want to remove your dependency on those. -
Review the new default's changes to
webpacker.yml
andconfig/webpack
. Consider each suggested change carefully, especially the change to have yoursource_entry_path
be at the top level of yoursource_path
. -
Make sure that you can run
bin/webpack
without errors. -
Try running
RAILS_ENV=production bin/rails assets:precompile
. If all goes well, don't forget to clean the generated assets withbin/rails assets:clobber
. -
Run
yarn add webpack-dev-server
if those are not already in your dev dependencies. Make sure you're using v4+. -
In
bin/webpack
andbin/webpack-dev-server
, The default NODE_ENV, if not set, will be the RAILS_ENV. Previously, NODE_ENV would default to development if not set. Thus, the old bin stubs would use the webpack config corresponding toconfig/webpack/development.js
. After the change, ifRAILS_ENV
istest
, thenNODE_ENV
istest
. The final 6.0 release changes to using a singlewebpack.config.js
. -
Now, follow the steps above to get to shakapacker v6 from webpacker v6.0.0.rc.6