Importing modules in JavaScript, are we doing it right?

We as Javascript developers need to use libraries in our day to day, it simplifies our work a lot. Nowadays we do that in this way mostly:

import * as lib from ‘amazing-lib’
import { func1 } from ‘amazing-lib’

If we quickly analyze it, in the …

We as Javascript developers need to use libraries in our day to day, it simplifies our work a lot. Nowadays we do that in this way mostly:

import * as lib from 'amazing-lib'
import { func1 } from 'amazing-lib'

If we quickly analyze it, in the first statement we are importing everything and putting it on a variable called lib, on the second, we are importing everything again and destructuring only what we need; what about all the other code that I’m not using?



Will not all the unused library’s code end up on the final bundle making my application unnecessary heavier?

Today you will learn how to improve your bundle size just by changing the way you import. After this, you are going to be able to detect a simple optimization opportunity for your bundle!



TL; DR

Verify if the library has support for ES6 and you can import freely, you will get always the best result ?‍♂️. If it doesn’t ⚠️, you need to import using cherry-picking.



Can we import as we want without consequences?

When we compile our front-end apps, there is a process that Webpack applies called Tree Shaking. Basically, is code elimination, the code that is not being used by anyone. This process prevents having dead code in our final bundle, making it lighter and the application is going to load faster for our users!

Let’s analyse this:

import * as lib from 'amazing-lib'
import { foo } from 'amazing-lib'

In both cases all the library content is being imported, the first place is the easiest to spot, all the library’s content is being assigned to the variable lib, in the second case we are just applying destructuring to the library’s content to get what we need. Thanks to Tree Shaking all the unused code doesn’t end up on our bundles.

So, thanks to Tree Shaking I’m excused and I can import however I want and all the unused code imported from the library will be removed automagically?

Not always is the case

There is a scenario when Tree Shaking is not going to be able to detect what is dead code having as consequence to remove nothing.



Scenarios



ES6

ECMAScript 2015(aka ES6) Module Syntax; it sounds complex, but it’s something really popular nowadays. It’s just a syntax to import a JS module, it looks like this:

import { foo } from 'awesome-lib'
import { bar } from '../utils'
import * as lib from '../utils'

export const justAConst = 'foobar'

When you are using a library that has ES6 Module Syntax compatibility, you don’t need to worry, import as will, Tree Shaking have you covered ?. In fact, is the only module syntax that Tree Shaking supports, let’s take a look at the documentation:

Tree shaking is a term commonly used in the JavaScript context for dead-code elimination. It relies on the static structure of ES2015 module syntax, i.e. import and export

The webpack 2 release came with built-in support for ES2015 modules (alias harmony modules) as well as unused module export detection…



If you are completely new about ? JS Modules



No ES6 module syntax

A library can be delivered (packaged) with other module systems different than ES6, even though if its source code uses ES6 module syntax, a compilation process could be implemented to only support CommonJS for example. The projects written using pure JS (with no transpilation process (Babel, TypeScript)) that uses the CommonJs module system is another example.

So, no ES6 module syntax present = no Tree Shaking. The only way to have a healthy bundle when dealing with libraries with no ES6 is importing using a technique called cherry-picking, you need to specify the absolute path to the file that contains the info needed.

import { small } from 'common-js-lib/small';



Downsides

Doing only cherry-picking has downsides:

  • You need to know the path to the module needed. (Your IDE could help in this quest)
  • You need to specify each one of the imports that you need, ex:

    import has from 'lodash/has';
    import capitalize from 'lodash/capitalize';
    import lastIndexOf from 'lodash/lastIndexOf';
    
  • As a maintainer, you may want to have a nice and easy-to-use scaffolding design to detect with ease something in your lib. This needs to be designed, implemented, and maintained.

  • You may forget to do it (ESLint can help) making your bundle unnecessary heavier



Test Performed

Having the theory learned I decided to prove all this. What I did was create some libraries with different module support, create several front-end apps on React and Angular1 to test if Tree Shaking really does its job.

The libraries created were simple, they export two variables small and big. small has as a value a doge ?, small = '?' but big instead has 1646400 doges, big = '?????????...'. This is going to make big to be 6.3 megabytes of weight.

Only small is going to be use at all time, so if big sneaks into the final bundle we are going to notice it on sight!.



Healthy Bundle

This how a healthy bundle looks like:
a healthy, bundle of 211.78KB



Smelly Bundle ?

The smelly one! You can notice a big white box that represents big and represents 96.7% of the application size:
Smelly Bundle, bundle of 6.49MB



Results

The results were as expected, if your library has to offer ES6 module syntax, Tree Shaking will do its job. If not, cherry-picking was the only way to get a healthy bundle.

Here is the repo if you are curious dianjuar/how-to-import. All this was created in a Monorepo using Nx, the library’s npm publishing was mocked using yalc. The bundle analysis was made using source-map-explorer.

Also, I wanted to make this test with popular libraries, so this is what I got, importing as import { whatINeed } from 'popular-lib'



Useful Tools

Along with this experiment, I was using the VsCode extension Import Cost and was precise along with the result. With the extension, you will be able to see right away how much an import will cost to the bundle. It will not tell you when you are getting a healthy or smelly bundle, but you can tell when an import cost is sus.

Import Cost Live



Gif extracted from the README of Cost Import



Conclusion

Tree Shaking have you covered! You can import however you want and you will be getting a healthy bundle if and only if the library has support for ES6 Module Syntax (import and export).

You can make your bundle unnecessary heavy if you don’t cherry-pick the imports on libraries without ES6 module support, like lodash.

Import Cost can help you to spot an import that needs some refinement.

  1. The experiment is agnostic to the Framework or Library used, if webpack is involved in the bundling it would take the same effect. 


Print Share Comment Cite Upload Translate
APA
Diego Juliao | Sciencx (2024-03-28T17:09:55+00:00) » Importing modules in JavaScript, are we doing it right?. Retrieved from https://www.scien.cx/2021/08/31/importing-modules-in-javascript-are-we-doing-it-right/.
MLA
" » Importing modules in JavaScript, are we doing it right?." Diego Juliao | Sciencx - Tuesday August 31, 2021, https://www.scien.cx/2021/08/31/importing-modules-in-javascript-are-we-doing-it-right/
HARVARD
Diego Juliao | Sciencx Tuesday August 31, 2021 » Importing modules in JavaScript, are we doing it right?., viewed 2024-03-28T17:09:55+00:00,<https://www.scien.cx/2021/08/31/importing-modules-in-javascript-are-we-doing-it-right/>
VANCOUVER
Diego Juliao | Sciencx - » Importing modules in JavaScript, are we doing it right?. [Internet]. [Accessed 2024-03-28T17:09:55+00:00]. Available from: https://www.scien.cx/2021/08/31/importing-modules-in-javascript-are-we-doing-it-right/
CHICAGO
" » Importing modules in JavaScript, are we doing it right?." Diego Juliao | Sciencx - Accessed 2024-03-28T17:09:55+00:00. https://www.scien.cx/2021/08/31/importing-modules-in-javascript-are-we-doing-it-right/
IEEE
" » Importing modules in JavaScript, are we doing it right?." Diego Juliao | Sciencx [Online]. Available: https://www.scien.cx/2021/08/31/importing-modules-in-javascript-are-we-doing-it-right/. [Accessed: 2024-03-28T17:09:55+00:00]
rf:citation
» Importing modules in JavaScript, are we doing it right? | Diego Juliao | Sciencx | https://www.scien.cx/2021/08/31/importing-modules-in-javascript-are-we-doing-it-right/ | 2024-03-28T17:09:55+00:00
https://github.com/addpipe/simple-recorderjs-demo