paint-brush
Reduce JS Bundle Size by Dynamically Importing es6 Modulesby@aldrinvincent
2,743 reads
2,743 reads

Reduce JS Bundle Size by Dynamically Importing es6 Modules

by AldrinMarch 2nd, 2022
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

Reducing the initial JavaScript bundle size can improve the performance of your application. Less javascript browser needs to parse and compile initially, the less will be the loading time. A smaller bundle size means the page will be interactive sooner for the user and the same will help in improving core web vital metrics like First Input Delay or First Contentful Paint.

Company Mentioned

Mention Thumbnail
featured image - Reduce JS Bundle Size by Dynamically Importing es6 Modules
Aldrin HackerNoon profile picture


Reducing the initial JavaScript bundle size can improve the performance of your application because the less javascript browser needs to parse and compile initially, the less will be the loading time.


Also, user interaction can be delayed if the browser’s main thread is busy executing JavaScript, so a smaller bundle size means the page will be interactive sooner for the user and the same will help in improving core web vital metrics like First Input Delay (FID) or First Contentful Paint (FCP).


One way to reduce JavaScript bundle size is to dynamically import es6 modules which are not required for the initial loading of the page. It is similar to code splitting in react where you lazily load react components on demand.


To dynamically import a module, the import keyword to be called as a function with a path to the module as an argument, when you dynamically import a module, you will get a promise that will resolve to an “all modules” object and you can get the corresponding exported function from the “all module” object.


const moduleSpecifier = "path_to_module"

import(moduleSpecifier).then(

    (allModules) => {
        // allModules will have all the modules exported from the file specified in the path, it is similar to import * as allModules from 'path_to_module'
        allModules.myfunction();
    },

    (error) => {
        // handle the error in loading or running the module, like network issue, exception in executing the function
    },

);

Example use case:

Consider the login page of a web application where the user enters e-mail/phone in the login form and the value needs to be validated to make sure the format is correct before sending it to the server for authentication. Here we don't need to import the validation function statically in the initial bundle because the validation function needs to be called only when the user starts filling the form or when the user submits the form, so instead of static import, we can import it dynamically when the user starts typing or when the user clicks on the submit button.


export function emailOrPhoneNumberValidator(value) {
     ...
}


import { useState } from "react";
const moduleSpecifier = "./validators";

export default function App() {
  const [userName, setUserName] = useState("");

  function validate(userName) {
    import(moduleSpecifier).then(
      (validatorModule) => {
        let isValid = validatorModule.emailOrPhoneNumberValidator(userName);
        console.log("isValid :>> ", isValid);
      },
      (error) => {
        console.log("error :>> ", error);
      }
    );
  }

  return (
    <div className="App">
      <input
        type="text"
        value={userName}
        onChange={(e) => setUserName(e.target.value)}
      />
      <br />
      <button onClick={() => validate(userName)}>Submit</button>
    </div>
  );
}


Here the validator function is not present in the initial bundle that was sent to the user's browser, it loaded only when the user clicked on submit button. In case the user didn’t submit the form, the validator bundle will not be loaded at all. We can view this in the browser’s network tab in the console, click on submit button and notice the validator module is fetched over a network call.


Dynamic import of es6 modules will be useful when you want to load and show a plugin/widget based on a configuration, you can lazily load the modules based on the configuration instead of loading all modules statically, this helps in better loading time and reduce bloating of the web app.