Migration to Webpack@2
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!