DEV Community

Jacopo Marrone @tresorama
Jacopo Marrone @tresorama

Posted on • Edited on

Maybe you don't know that Javascript can conditionally import

For a side project, I was creating a personal blog starter.
Without going into details, it's a Next.js project that use SSG to create every pages at build time.
You can decide "how and where" you write and store your articles.
The choice is between these datasources :

  • Flat File (version-controlled markdown file in a sub dir of the repo)
  • Notion Database

Both datasource are coded as an object with a type signature shared by every datasource, so that the view layer is decoupled from the real datasource implementation.

Both "flat-file" and "notion" strategies have code implementaion, this implementaion is located in different location inside the repo folder structure.
In case you use "notion" strategies, it is not necessary that the code imports the "flat file" code becasue it will be never used, and viceversa.

To solve this problem, at the beginning you must open a file and comment/uncomment a line of code, like this:

// 1. when notion is the choice
// import { flatFileDatasource as datasource } from './strategies/flat-file';
import { notionDatasource as datasource } from './strategies/notion';

export datasource;
Enter fullscreen mode Exit fullscreen mode

... or ...

// 2. when flat file is the choice
import { flatFileDatasource as datasource } from './strategies/flat-file';
// import { notionDatasource as datasource } from './strategies/notion';

export datasource;

Enter fullscreen mode Exit fullscreen mode

It works. But is not comfortable.

What if I can conditionally import a module or an other ?!??

Well, Javascript covers this case.

Dynamic Import

This syntax

import {something} from './someplace';
Enter fullscreen mode Exit fullscreen mode

is known as static import.

But javascript has also a dynamic and async import feature

import('./someplace').then(module=>console.log(module));
Enter fullscreen mode Exit fullscreen mode

that returns a promise with the imported module object.

Of course when you export a promise, who imports it must await before utilizing its resolved value, so you must adjust some other code as well.

Here is a generic example

// file: ./fancy-lib.ts

export let getLib: () => Promise<FancyLibType>;

if (today === 'monday') {
  getLib = () => import('./monday').then(module => module);
}
else if (today === 'friday') {{
   getLib = () => import('./friday').then(module => module);
}
else {
  throw new Error(`No libraries for ${today} day`);
} 


// file: ./consumer-of-fancy-lib.ts
import { getLib } from './fancy-lib';

const manipulation = async () => {
  const myLib = await getLib();
  // ... rest of the code
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

Dynamic import lets you import modules based on conditions that are computed at runtime, opening the possibility to avoid loading unnecessary code.

Due to the nature of the feature, that utilizes Promise, some other code needs to be updated as async as well.


And you?
Have you ever used dynamic import?
Do you have a static alternative for conditional import? Feel free to share.


Resources

MDN - import - static

MDN - import() - dynamic

Top comments (2)

Collapse
 
wiseolddj profile image
DJ Clack

I have only seen this in the wild to load Dev tools on non production environments. Looks like testing this sort of use case would be a lot of extra work and probably only worth the benefit if the code is rather bloated.

Collapse
 
tresorama profile image
Jacopo Marrone @tresorama

I never used it other than this project, I admit it.
Which main pain points did you encounter?