Despite being widely used today, Webpack is still a black box for many developers who simply use an existing configuration without knowing how it really works.
So, today we will cover some of the key parts of Webpack to help you understand its operation and to be able to optimize our Webpack configuration according to our needs.
For this we will start explaining some Webpack modules and we will see how they can help us.

 

Webpack modules

 

Modules

Using Webpack modules we can divide our code into different files, so that each file has a single responsibility, which will make our code much more understandable and easy to test.

In order to carry it out we will use the ES6 imports as they allow us to import and export our dependencies to use them in other modules. Despite being very useful, the use of imports without control can generate performance problems when importing very heavy modules or importing modules that are not really necessary until the user interacts with certain sections of the application, so that means that we should not call them from a start. To solve both problems we will talk about Tree shaking and Dynamic imports.

 

Tree Shaking

The concept of Tree Shaking is very easy to understand. Webpack analyzes our modules in search of imports and exports and when it finds a module that imports or exports content and it is not used, it discards it to avoid having a dead code.
Here we can see an example:

employee.js
export const firstName = 'Arnau';
export const lastName = 'Silvestre Dulcet';
export const position = 'Frontend';
export const company = 'Apiumhub';

Index.js
import { firstName, lastName, company, position } from './employee';

console.log(firstName, lastName, company, position);

When executing the following code using all the constants that we have imported from employee we see that for the file index.js (where we do our imports) it generates a bundle of 122 bytes. In this case Tree shaking is not acting, because as we use all our imports, there is nothing to discard.

However, in the following case:

import { firstName, lastName, company, position } from './employee';

console.log(firstName, company);

We only use firstName and company, and although we also import lastName and position, we are not using them in our code, so Webpack discards them.

Thanks to that we can reduce the size of our bundle. Although in our example it only results in a difference of 20 bytes, let me highlight that it is a very simple example, but in a project it can result in a huge difference.

In order to activate this functionality we will add the sideEffects: false in the first level of our package.json, indicating that our project does not contain side effects and thus allowing Tree shaking.

{
  "name": "projectName",
  "version": "0.0.0",
  "license": "MIT",
  "sideEffects": false
}

As Webpack’s own documentation says: A side effect is defined as the code that performs some special action when imported, apart from defining its exports.

 

Dynamic imports

The use of dynamic imports allows us to import a module anywhere in our file, allowing us to import content under certain circumstances, thus reducing the loading time of our pages. This is especially useful if we work with very heavy modules and we only need one of them to navigate.
We do not need any specific configuration of Webpack, starting with v2, in order to use dynamic imports.

For example,

setTimeout(importModule(), 3000);

function importModule() {
    import('./employee').then(myModule => {
        console.log(myModule);
    });        
}

In the previous example, the variable myModule contains the information of our module (variables, methods …)

 

The dynamics imports are usually used to load the different contents of the pages according to the state of our navigation. Why should I upload the contents of the About or Contact section of my page if I am only displaying the Home?

 

Tree Shaking and Dynamic imports

After having presented you both, we will talk about the compatibility problems at the time of using them together.

if(admin == true) { import('./admin').then(myModule => { console.log(myModule); }); } 

And a static import:

import {person} from ‘./person.js’; 

Webpack can not know in advance if the dynamic import is going to be used at some point, so in those cases you can not apply Tree Shaking and can not be sure that dynamic imports will never be used.

Keeping this in mind at the time of preparing our Webpack configuration, we must think about what we want to achieve and if we want to use one or the other, or both. We must think about the strategy that we are going to follow, in order to use them together and get both functions to complement each other instead of colliding.

 

If you are interested in Webpack modules or in software development in general, I highly recommend you to subscribe to our monthly newsletter

 

If you found this article about Webpack modules interesting, you might like…

 

Scala generics I: Scala type bounds

Scala generics II: covariance and contravariance  

Scala Generics III: generalized type constraints

BDD: user interface testing

F-bound over a generic type in Scala

Microservices vs Monolithic architecture

“Almost-infinit” scalability