Nathaniel's blog
Back to posts

ES-Next dynamic import

Nathaniel LinAugust 28, 20192 min read11 views
ES-Next dynamic import

Problem

Recently when writing a project of mine, I've written some javascript like this:

import itemA from '../items/itemA'; import itemB from '../items/itemB'; import itemC from '../items/itemC'; import itemD from '../items/itemD';

I'd really like some syntax like this:

for(const id of ['A','B','C','D']) {

 import (item+id) from '../items/item'

+ id; }

Turned out there's this stage 4 proposal of ECMAScript called dynamic import

that goes like:

(async () => {

 await import('./my-app.mjs'); })();

and it's supported by all modern browsers as well as node.

Failed Attempt

Then I went on writing some line code like this:

importedItems = await Promise.all(

 itemNames.map(async itemName => {

 try {

 const imported = await import(`../items/${itemName}`);

 logger.debug(`Imported item: ${itemName}`);

 return imported;

 } catch (err) {

 logger.warning(`Failed to import item: ${itemName}`);

 return null;

 }

 }) );

But for later use of importedItems, a TypeError has been raised stating that the importedItems are actually type of Module instead of expected item. I tried manual type casting like this:

return Item(imported);

But it didn't work and since it's not yet standardized feature (Due to be standardized in ECMAScript 2020), there's little information about it so I have to figure it out myself.

After a long time with JSON.stringify() and console.log I finally figured it out.

Solution

It should work like this:

return imported.default;

Full working snippet

importedItems = await Promise.all(

 itemNames.map(async itemName => {

 try {

 const imported = await import(`../items/${itemName}`);

 logger.debug(`Imported item: ${itemName}`);

 return imported.default;

 } catch (err) {

 logger.warning(`Failed to import item: ${itemName}`);

 return null;

 }

 }) );

Reason

The reason is that when we use an import statement like this:

import item from './itemA';

it automatically loads the default export of module 'itemA' into the item.

But when we do expression like dynamic import like this:

(async () => {

 const item = await import('./itemA'); })();

the item is a Module , by accessing Module.default we are able to fetch its default export, same goes for any other exports.

Share this post

Reactions

ES-Next dynamic import | Nathaniel's blog