This is a short overview of things that are required to upgrade a project from the Asset Pipeline to Webpacker. Expect this upgrade to take a few days even the diff is quite small afterwards.
Preparations
1. Find all libraries that are bundled with the asset pipeline. You can check the application.js
and the application.css
for require
and import
statements. The source of a library is most often a gem or a vendor directory.
2. Find an working example for each library in the application and write it down.
3. Find out the version of the library you are actually using and write it down. It depends how you can archive this, but this might help you:
- The gem version might reflect the actual library version
- The gem states the library version in the README.md or the NPM link
- The source files have a version in their top comment
4. Find out which libraries are published on NPM in the correct version and write it down. Other libraries have to be copied to a private node package into the project.
Introduce Webpacker
1. Install
Webpacker
Show archive.org snapshot
2. Check if css extraction is enabled in webpacker.yml
:
# Extract and emit a css file
extract_css: true
3. Change stylesheet_link_tag
to stylesheet_pack_tag
and javascript_include_tag
to javascript_pack_tag
4. Replace image_tag
with image_pack_tag
if it uses an asset. For more information view section "Adding images" in Webpack(er) primer
5. Add all libraries that are available via NPM to your package.json
with the correct version. All others need to be packaged as a private NPM package. Freeze your jQuery version if desired. Here is an example how this might look:
{
"dependencies": {
"@rails/webpacker": "4.x",
"bootstrap-datepicker": "1.8.0",
"bootstrap-sass": "3.4.1",
"font-awesome": "4.7.x",
"jquery": "2.2.4",
"marked": "0.3.2",
"select2": "./vendor/asset-libs/select2",
},
"devDependencies": {
"webpack-dev-server": "3.x"
},
"resolutions": {
"jquery": "2.2.4"
}
}
6. Merge the content of the application.js
and application.css
to the app/webpack/packs/application.js
. You can also import the modules in other files, like the app/webpack/stylesheets/boostrap.sass
imports the bootstrap stylesheet. For old Javascript libraries you need to expose jQuery
to the window
object. Here is an example how this might look like.
app/webpack/packs/application.js
import jQuery from 'jquery'
import 'bootstrap-sass/assets/javascripts/bootstrap.js'
import 'bootstrap-datepicker/dist/js/bootstrap-datepicker.js'
import 'bootstrap-datepicker/dist/css/bootstrap-datepicker3.css'
import 'clockpicker/dist/bootstrap-clockpicker.js'
import 'clockpicker/dist/bootstrap-clockpicker.css'
// select2 is packaged locally as version 3.5.4 was never published https://github.com/select2/select2/issues/5360
import 'select2/select2.js'
import 'select2/select2.css'
import 'select2/select2-bootstrap'
import 'jquery-ujs'
window.$ = jQuery
window.jQuery = jQuery
// JavaScript
let webpackContext = require.context('../javascripts', true, /\.js$/)
for(let key of webpackContext.keys()) { webpackContext(key) }
// Images
require.context('../images', true, /\.(?:png|jpg|gif|ico|svg)$/)
// Stylesheets
require.context('../stylesheets', true, /\.sass$/)
app/webpack/stylesheets/bootstrap.sass
$icon-font-path: '~bootstrap-sass/assets/fonts/bootstrap/';
@import "~bootstrap-sass/assets/stylesheets/_bootstrap";
import marked from 'marked';
marked.setOptions({
sanitize: true
});
window.marked = marked;
7. Try to successfully boot the application.
8. Fix all broken JS and CSS libraries. Go step by step from one library to the next with the example written down before. Always check your console for missing files and errors. Compare screens to find missing stylesheets.
- Some gems give you ruby code. You need to copy this code to your project, if you used it.
Here
Show archive.org snapshot
is an example for the
icon
helper in thefont-awesome-sass
gem. - You need to check and verify which parts of a library you want to import to your project. Many gems include everything because it was not possible otherwise. But now you can choose if you need all 50+ languages of a datepicker or just the english one. Most often you want to import beside the default JS defined in the
package.json
the styles of the library. - Always try to import the
dist
of a node package. Sometimes (e.g. PhantomJS will die with some ES6 syntax) it is even required to import somelegacy
prefixed files from the dist folder, which is most often <ES6 javascript.
9. Achieve green tests.
10. Check if postcss
, uglifier
, babel
and other compilers work for production. This can be done by compiling the packs for production and search for a working example: RAILS_ENV=production bundle exec rake assets:precompile
. Remember to remove the folder public/packs
afterwards.
11. Configure Capistrano and servers such that all servers share assets
12. Add a binstub for yarn if it's missing
Cleanup
- Remove all gems you used for assets and the Asset Pipeline itself, e.g.
sass-rails
,uglifier
,autoprefixer-rails
,sprockets-rails
,jquery-rails
,bootstrap-sass
and many more. - Remove Asset Pipeline configurations from
app/config/application.rb
andapp/config/environments/*
. - Remove libraries from the
vendor
folder. - Remove
require "sprockets/railtie"
fromapplication.rb
Configure Deployment
See Configuring Webpacker deployments with Capistrano.
Deploy
- Check if your servers have the correct version of node and yarn installed.
- Deploy and check if everything is working properly.
- Remove the public/assets directory on the servers of each deploy stage. Webpacker's assets live in public/packs.