Back

ES-Next dynamic import

Thu, Aug 29 20192 min read
Nathaniel

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.

Comments(0)

Continue with
to comment