Webpack: Optimize your creations

webpack

What is Webpack ?

Webpack is a static module bundler for your javascript applications, it helps you bundle all your dependencies, assets, code and compile them to javascript.

Why do we need Webpack ?

Now the question arises why we need Webpack, most of the frameworks and libraries based on javascript has some already defined boilerplates by the community. Be it React JS , Vue JS, Angular JS etc.

Recently, I had an opportunity to upgrade Webpack from version 3 to version 4, I heard Webpack 4 is something we’ve never experienced before. I was excited to see how it works out. There were two objectives in my mind when I first started:

  • Upgrade to Webpack 4 from Webpack 3
  • Reduce the build size of the production build (Optimize the Webapck configurations)

For your information, the project I had to upgrade Webpack was a Vue JS project. Firstly, we’ll be seeing what were the results before and after upgrading, then we will explore a package which lets us visualise how much space is utilised by which library, then we’ll explore some of the techniques you can use to optimize your Webpack builds along with there practical examples.

So? Excited? Let’s get started…

1. Before and After Webpack optimization

In programming, it is always better to know what was the initial problem statement and what was the end result once the problem was solved by an appropriate solution. So below are some statistics related to the projects build

BEFORE OPTIMIZATION PERFORMANCE

NOTE: Following statistics are logged by using the Audit tool provided by Google chrome devtools.

Consider the following settings while testing:

  • Device: Desktop/Mobile respectively of which you want to measure performance
  • Audits: Select all
  • Throttling: Applied Fast 3G, 4x CPU Slowdown
  • Clear Storage: Checked

Results of performance:

  • Desktop: 2
  • Mobile: 3

NOTE: Following statistics are from manual testing using a package named Webpack bundle analyzer(which we’ll be talking about in this article)

  • Stat : 8.28MB in dev and 5.55MB in prod
  • Parsed : 3.9MB in dev and 2.64MB in prod
  • Gzipped : 1.02MB in dev and 806KB in prod
  • dist folder : 28.7MB in dev and 25.4MB in prod

AFTER OPTIMIZATION PERFORMANCE

Build Time: CHECK THIS AND ADD IT HERE?**NODE_ENV = development and NODE_ENV = production is the only difference between dev and prod environments

NOTE: Following statistics are logged by using the Audit tool provided by Google chrome devtools.

Consider the following settings while testing:

  • Device: Desktop/Mobile respectively of which you want to measure performance
  • Audits: Select all
  • Throttling: Applied Fast 3G, 4x CPU Slowdown
  • Clear Storage: Checked

Results of performance:

  • Desktop: 18
  • Mobile: 23

NOTE: Following statistics are from manual testing using a package named Webpack bundle analyzer(which we will be talking about in this article below).

  • Stat: 6.76MB
  • Parsed: 3.87MB
  • Gzipped: 972KB
  • dist folder: 24.3MB
  • Build Time: 132933ms
  • **NODE_ENV = production

STEPS TO PERFORM

Webpack Optimization

  • Update webpack from 3 to 4
  • Upgrade webpack from 3 to 4
    • Splitting app package into  main  and vendor (Bundle Splitting)
    • Other mandatory changes
  • Splitting out each npm package
  • Facing migration problems

Code Splitting

  • Using dynamic imports for components and for routes

Code Optimization

  • Add loader in-between route switching
  • Lazy load 3rd party libraries (Coming Soon..)

WEBPACK OPTIMIZATION

Update webpack from 3 to 4

This step was a pain to perform. I’ll write this down in a very crude way so as to get the essence of the problems in a sequential manner

To upgrade, you have to install webpack-cli for it

Command:

npm i -D webpack webpack-cli

Results:

  • Problem: webpack-cli was installed with 3.3.4 version. But I didn’t see that webpack version was upgraded and it was still 3.6.0.
  • Solution: Then I manually updated package.json file with webpack version as 4.33.0

Now, remove all node modules from your project directory

rm -rf node_modules

And now install all the node modules again

npm install

And, now it was updated. Upgrading is still pending, which is somewhat manual

Check any package version:‘npm list <package_name>’For eg.‘npm list webpack’

Upgrade webpack from 3 to 4

This step includes bundle splitting, i.e. we have to now split our single entry point file into two i.e. main.js and vendor.js

Add the following code in the webpack.base.conf.js` (file convention may change)

optimization: {
    splitChunks: {
      chunks: 'all',
    },
  }

Note: ‘Optimization’ property can only used if you have webpack 4, otherwise, you have to use ‘CommonsChunkPlugin’. And, this was also one of my reason to migrate from w3 to w4 (w=webpack)

This will basically add all the node_modules related stuff into vendor.js file and your code related stuff into main.js

Other mandatory changes as referred by official webpack migration steps:

  1. Add production mode in the same file
    1. mode: ‘production’,
  2. Add Plugins as recommended by webpack in the plugins section
    1. new webpack.HashedModuleIdsPlugin({ }),
  3. Remove the not required plugins (if in production mode)
    1. https://webpack.js.org/migrate/4/#deprecatedremoved-plugins
  4. Remove ‘CommonsChunkPlugin’ while using ‘optimization’ property mentioned above

Splitting out each npm package

Replace optimization property which was added above:

optimization: {
    runtimeChunk: 'single',
    splitChunks: {
      chunks: 'all',
      maxInitialRequests: Infinity,
      minSize: 0,
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name(module) {
            // get the name. E.g. node_modules/packageName/not/this/part.js
            // or node_modules/packageName
            const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1];
            // npm package names are URL-safe, but some servers don't like @ symbols
            return `npm.${packageName.replace('@', '')}`;
          },
        },
      },
    },
  },

Facing migration problems

If you have already been using dynamic imports you might face the following problems while trying to build the app. The solution worked for me was:

  • Remove package-lock.json file
  • Add acron package. “acorn“: “^6.0.5“,
  • Remove node_modules
  • npm install 

You need to also update some packages in the package.json file, viz.

Obsolete packages upgradation

  • ‘Extract-text-webpack-plugin’ would not work in w4. Instead, we have to import ‘mini-css-extract-plugin’ and remove all occurrences of the ‘Extract-text-webpack-plugin’. I still have to configure this properly for production mode.

Code Splitting

I followed this article for splitting my VueJs code. You can find similar things for your framework.

Code Optimization

Now we know that all the routes are lazy-loaded and there would be a very tiny lag affecting user experience. Hence, I decided to add loader when route is changed every time. I configured it in my vue js app like this:

My app’s main.js file looks like:

import router from './router'
import App from './App.vue'
/* eslint-disable no-new */
const app = new Vue({
  el: '#app',
  data: { loading: false },
  router,
  components: { App },
  template: ''
})
router.beforeResolve((to, from, next) => {
  app.loading = true
    next()
})
router.afterEach((to, from) => {
  app.loading = false
})
And, App.vue template looks like this:

RESOURCES

BLOGS/ARTICLES

Today we have covered optimizing web applications using webpack.

I hope this was a helpful article. Visit Tweeny blog regularly for more informative articles on tech and our customer’s case studies where we work with some of the bleeding edge technologies.

Leave a Reply

Your email address will not be published. Required fields are marked *