Migration to Webpack@2

react on railsJanuary 05, 2017Dotby Alex Fedoseev

I spent the past few days upgrading our app to the latest RC of Webpack ver. 2. Here’s the official migration guide, that covers most of the common cases, but there were still a number of “gotchas” that I wish I had been aware of before I started this PR.

Dependencies

Most Webpack’s related dependencies that have been updated to be compatible with the new API are published as beta/next. You will need to specify these special Webpack@2-compatible semantic versions manually since the regular update flow will not pick them up due to the beta/next tag.

Loader declaration

The next version of Webpack doesn’t allow shortcuts in the loader declaration anymore (e.g., you can’t declare babel-loader as 'babel', only as 'babel-loader'). In cases where you use the shortcut in your config, it’s easy to spot, because it’s scoped to config, but not scattered over the codebase. Also Webpack makes it clear in the error message, if it can’t find module with the same name as shortcut. But, if you use the short version of the loader name outside of your config in one of your source files, such as importing an icon for your React component:

import icon from '!!url!./icon.svg';

and you have a module named url in your node_modules folder, you will see this error:

Error: Module 'path/to/node_modules/url/url.js' is not a loader
(must have normal or pitch function)

It’s not clear where this problematic declaration actually is, because the location of the import is not included in the error message. Considering that such imports are used in very rare cases and so much is changing when updating to Webpack@2, it might be hard to track down the root of the issue.

node-sass

We’re using Sass in our stack to take care of CSS. To build our assets, we’re using [email protected] In development we also use webpack-dev-server to hot reload assets.

When I updated deps, incl. [email protected] (latest), and ran the development environment, dev server reported that it was listening to the port and… process just hanged. Later on I tried to build from CLI and finally received feedback in the form of segfaults, which led me to node-sass after some googling. A rollback to [email protected] solved issue.

By the time you read this article, [email protected] might work.

Also, if you ran server, but the process for webpack-dev-server became unresponsive, and the kill PID command doesn’t kill the process, use kill -9 PID to free the port.

ExtractTextPlugin

This thing took almost a day. The new module API looks like this:

module: {

  rules: [

    {

      test: /\.css$/,

      use: 'css-loader',

    },

  ],

},

But when you apply ExtractTextPlugin it must be:

module: {

  rules: [

    {

      test: /\.css$/,

      loader: ExtractTextPlugin.extract({ ... }),

//    ^

//    not `use`, but `loader`!

   },

  ],

},

Full example with CSS modules, PostCSS & SCSS:

{

  test: /\.scss$/,

  loader: ExtractTextPlugin.extract({

    fallbackLoader: 'style-loader',

    loader: [

      {

        loader: 'css-loader',

        query: {

          minimize: true,

          modules: true,

          importLoaders: 2,

          localIdentName: '[name]__[local]__[hash:base64:5]',

        },

      },

      'postcss-loader',

      'sass-loader',

    ],

  }),

},

resolve-url-loader

If resolve-url-loader is used, you must provide the config.output.path value via webpack.LoaderOptionsPlugin as loaders don’t have access to this data anymore.

Link to suggestion with code example

expose-loader

We expose jQuery for some legacy libs. With Webpack@1 it was done like this:

{

  test: require.resolve('jquery'),

  loader: 'expose?$!expose?jQuery',

},

Same, but for Webpack@2:

{

  test: require.resolve('jquery'),

  use: [

    {

      loader: 'expose-loader',

      query: 'jQuery',

    },

    {

      loader: 'expose-loader',

      query: '$',

    },

  ],

},

Have a smooth upgrade!


P.S. You should follow us on Twitter: @alexfedoseev | @shakacode

P.P.S. Thanks, @RobAWise for reviewing this!

Closing Remark

Could your team use some help with topics like this and others covered by ShakaCode's blog and open source? We specialize in optimizing Rails applications, especially those with advanced JavaScript frontends, like React. We can also help you optimize your CI processes with lower costs and faster, more reliable tests. Scraping web data and lowering infrastructure costs are two other areas of specialization. Feel free to reach out to ShakaCode's CEO, Justin Gordon, at [email protected] or schedule an appointment to discuss how ShakaCode can help your project!
Are you looking for a software development partner who can
develop modern, high-performance web apps and sites?
See what we've doneArrow right