Migration from the Asset Pipeline to Webpacker

Updated . Posted . Visible to the public.

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 the font-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 some legacy 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

  1. 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.
  2. Remove Asset Pipeline configurations from app/config/application.rb and app/config/environments/*.
  3. Remove libraries from the vendor folder.
  4. Remove require "sprockets/railtie" from application.rb

Configure Deployment

See Configuring Webpacker deployments with Capistrano.

Deploy

  1. Check if your servers have the correct version of node and yarn installed.
  2. Deploy and check if everything is working properly.
  3. Remove the public/assets directory on the servers of each deploy stage. Webpacker's assets live in public/packs.
Last edit
Klaus Weidinger
Keywords
migrate
License
Source code in this card is licensed under the MIT License.
Posted by Emanuel to makandra dev (2019-04-23 11:49)