ES2020 — Dynamic Import🔥 (Code Splitting)

Abhishek Gautam
3 min readFeb 4, 2021

In ES2015 (aka ES6) for the first time a native JS module system was added but the main problem with this is that it is static import meaning it can’t be changed at the runtime and also all imports need to be resolved before JS could execute any code which I feel sucks.

In ES2020 the TC39 approves the proposal for dynamically importing modules. So now instead of having all imports at top of the file, you can import modules whenever required. However, this feature was supported by webpack.

The major benefit which we can get from dynamic imports is that we can have a faster load time. Also if some modules don’t exist on load time they can be dynamically loaded at a later point in time. We can split code and load only what matters at the current point in time. It may make the app more robust by not failing to load all essential modules during the initial load.

Dynamic imports are not here to replace the static imports both have their own use cases. Static import can be used for initially required dependencies whereas in other cases load modules on demand.

How?

For dynamically importing, the import keyword must be called as a function that returns a promise. Let’s consider we have a util.js which have some named and default exports.

// util.jsexport function doSomthing() {   console.log("Named Export");}export default function doSomethingDefault() {console.log("Default Export");}

Now we can dynamically import it as

const btn = document.getElementById("btn");btn.addEventListener("click", () => {// loads named exportimport("./util.js").then(({ doSomething}) => {doSomething();});// loads entire module// runs default exportimport("./util.js").then((module) => {module.default();});});

Another way of extracting the import logic to the top is file can be done as follow, here the loadUtil method returns a promise which can be chained.

const loadUtil = () => import("./util.js");const btn = document.getElementById("btn");btn.addEventListener("click", () => {loadUtil().then(module => {module.doSomething();module.default();}); });

Dynamically Importing JSON file

A good thing about ES modules is that unlike CommonJS and AMD is that ES modules can be any JS object string, JSON, constructor, functions, etc.

const loadConfig = () => import("./config.json")

JSON files just have a default export so you can access the object using the module.default and de-structure it.

Dynamic Import with Async/Await

As we have already figured out that import() returns a promise meaning we can async/await on it.

const loadConfig = () => import("./config.js");const btn = document.getElementById("btn");btn.addEventListener("click", async () => {const ConfigModule = await loadConfig();configModule.doSomthing();configModule.default();});

import() is just like a function but not a function

The way we use import may make it look as if it is a function but it isn’t because it doesn’t inherit from Function.prototype so we cannot call bind, apply on it.

Please find the official MDN Link for further exploring

Happy Learning!

--

--

Abhishek Gautam

A tech geek who loves to solve problems and coming up with meaningful, simplistic solutions.