Webpack: Optimize your creations (v3-v4)
Webpack is an open-source module bundler for JavaScript applications. It is used to bundle and package the various assets that make up a web app
What is Webpack?
Webpack is a static module bundler for your javascript applications, it helps you bundle all your dependencies, assets, and code and compile them to javascript.
Why do we need Webpackas to?
Now the question arises as to why we need Webpack, most of the frameworks and libraries based on javascript have 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 worked out. There were two objectives in my mind when I first started:
- Upgrade to Webpack 4 from Webpack 3
- that
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 that 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 for migratingWebpack 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:
- Add production mode in the same file
- mode: ‘production’,
- Add Plugins as recommended by Webpack in the plugins section
- new webpack.HashedModuleIdsPlugin({ }),
- Remove the not required plugins (if in production mode)
- https://webpack.js.org/migrate/4/#deprecatedremoved-plugins
- Remove ‘CommonsChunkPlugin’ while using the Webpack‘optimization’ property mentioned above
Splitting out each npm package
Replace the thatoptimization 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:
You need to also update some packages in the package.json file, viz.
- HtmlWebpackPlugin “html-webpack-plugin“: “^3.2.0“,
- WebpackDevServer “webpack-dev-server“: “^3.1.4“,
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
- Splitting Chunks
- Webpack 3 to 4
- Mode: Development vs Production
- Real experience of upgrading to webpack 4
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.