Upgrade to Webpack 4

olegchursin

Oleg Chursin

Posted on March 9, 2019

Upgrade to Webpack 4

The app we are currently working on at Aon Cyber Solutions (1) is an ejected CRA with TypeScript and Apollo GraphQL. To our pleasure we have webpack.config.dev.js and webpack.config.prod.js to play with and must make sure that both environments are working as expected.

While getting all excited to update our Storybook to v.5, we discovered that our Webpack also needs a facelift. So the time has come to enter Webpack 4 era.

Visiting the official migration guide is your natural first call. Followed the step-by-step instructions to no avail and some frustration. Googling, StackOverflowing and GitHubbing to the rescue. Well, well… I’m not the only frustrated one.

Here comes a step-by-step guide that led to successful yarn start and yarn build:

Step 1. Upgrade webpack and install webpack-cli:

yarn add webpack
yarn add webpack-cli
Enter fullscreen mode Exit fullscreen mode

version check:

// package.json
...
"webpack": "^4.29.6",
"webpack-cli": "^3.2.3",
...
Enter fullscreen mode Exit fullscreen mode

Step 2. Add respective modes in webpack.config.dev.js and webpack.config.prod.js

// webpack.config.dev.js
...
module.exports = {
    mode: 'development',
    ...
Enter fullscreen mode Exit fullscreen mode
// webpack.config.prod.js
...
module.exports = {
    mode: 'production',
    ...
Enter fullscreen mode Exit fullscreen mode

Step 3. Add fork-ts-checker-notifier-webpack-plugin

yarn add fork-ts-checker-notifier-webpack-plugin --dev
Enter fullscreen mode Exit fullscreen mode

version check:

// package.json
...
"fork-ts-checker-notifier-webpack-plugin": "^1.0.0",
...
Enter fullscreen mode Exit fullscreen mode

Step 4.1 Update html-webpack-plugin

yarn add html-webpack-plugin@next
Enter fullscreen mode Exit fullscreen mode

version check:

// package.json
...
"html-webpack-plugin": "^4.0.0-beta.5",
...
Enter fullscreen mode Exit fullscreen mode

Step 4.2 Adjust the plugin order in webpack.config.dev.js and webpack.config.prod.js

Make sure HtmlWebpackPlugin comes before InterpolateHtmlPlugin and the latter is declared as in the example below:

plugins: [
  new HtmlWebpackPlugin({
    inject: true,
    template: paths.appHtml
  }),
  new InterpolateHtmlPlugin(HtmlWebpackPlugin, env.raw),
...
Enter fullscreen mode Exit fullscreen mode

Step 5. Update ts-loader, url-loader and file-loader

yarn add url-loader file-loader ts-loader
Enter fullscreen mode Exit fullscreen mode

version check:

// package.json
...
"file-loader": "^1.1.11",
"ts-loader": "4.0.0",
"url-loader": "0.6.2",
...
Enter fullscreen mode Exit fullscreen mode

Step 6. Update react-dev-utils

yarn add react-dev-utils
Enter fullscreen mode Exit fullscreen mode

version check:

// package.json
...
"react-dev-utils": "6.1.1",
...
Enter fullscreen mode Exit fullscreen mode

Step 7. Sub extract-text-webpack-plugin with mini-css-extract-plugin

Get rid of extract-text-webpack-plugin altogether. Add and configure mini-css-extract-plugin.

yarn add mini-css-extract-plugin
Enter fullscreen mode Exit fullscreen mode

version check:

// package.json
...
"mini-css-extract-plugin": "^0.5.0",
Enter fullscreen mode Exit fullscreen mode

Config:

// webpack.config.prod.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

plugins: [
  ...
  new MiniCssExtractPlugin({
    filename: "[name].css",
    chunkFilename: "[id].css"
  }),
  ...
],
module: {
  rules: [
    {
      test: /\.css$/,
      use: [
      {
        loader: MiniCssExtractPlugin.loader,
        options: {
        // you can specify a publicPath here
        // by default it use publicPath in webpackOptions.output
        publicPath: '../'
      }
    },
    "css-loader"
  ]
},
Enter fullscreen mode Exit fullscreen mode

Step 8. Update and reconfigure uglifyjs-webpack-plugin

yarn add uglifyjs-webpack-plugin --dev
Enter fullscreen mode Exit fullscreen mode

version check:

// package.json
...
"uglifyjs-webpack-plugin": "^2.1.2"
Enter fullscreen mode Exit fullscreen mode

Config:

// webpack.config.prod.js
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
module.exports = {
  ...
  optimization: {
    minimizer: [new UglifyJsPlugin()],
  },
...
Enter fullscreen mode Exit fullscreen mode

Step 9. Fix any deprecation errors you may be getting. Follow the error message and trace and update any webpack plugins you may need to. In our case it was webpack-manifest-plugin.

I really hope this guide will save at least someone a few minutes/hours.


(1) This is a personal blog post that in no way reflects Aon Cyber Solution’s official opinion.


Sources that were used to come up with the working solution:

💖 💪 🙅 🚩
olegchursin
Oleg Chursin

Posted on March 9, 2019

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related