ES6: Conditional & Dynamic Import Statements
As this question is highly-ranked by Google, it is worth pointing out that things have changed since the older answers were posted.
MDN has this entry under 'Dynamic Imports':
The import keyword may be called as a function to dynamically import a module. When used this way, it returns a promise.
import('/modules/my-module.js') .then((module) => { // Do something with the module. }); This form also supports the await keyword. let module = await import('/modules/my-module.js');
A useful article on the subject can be found on Medium.
We do have dynamic imports proposal now with ECMA. This is in stage 2. This is also available as babel-preset.
Following is way to do conditional rendering as per your case.
if (foo === bar) {
import('./Baz')
.then((Baz) => {
console.log(Baz.Baz);
});
}
This basically returns a promise. Resolution of promise is expected to have the module. The proposal also has things like multiple dynamic imports, default imports, js file import etc. You can find more information about dynamic imports here.
You can't resolve dynamically your dependencies, as imports
are meant for static analysis. However, you can probably use some require
here, something like:
for (let foo in bar) {
if (bar.hasOwnProperty(foo)) {
const Baz = require(foo).Baz;
}
}
Since 2016 a lot has passed in JavaScript world, so I believe it's time to offer most updated info on this topic. Currently Dynamic imports are a reality both on Node and on browsers (natively if you don't care about IE, or with @babel/plugin-syntax-dynamic-import if you do care).
So, consider a sample module something.js
with two named exports and one default export:
export const hi = (name) => console.log(`Hi, ${name}!`)
export const bye = (name) => console.log(`Bye, ${name}!`)
export default () => console.log('Hello World!')
We can use import()
syntax to easily and cleanly load it conditionally:
if (somethingIsTrue) {
import('./something.js').then((module) => {
// Use the module the way you want, as:
module.hi('Erick') // Named export
module.bye('Erick') // Named export
module.default() // Default export
})
}
But since the return is a Promise
, the async
/await
syntactic sugar is also possible:
async imAsyncFunction () {
if (somethingIsTrue) {
const module = await import('./something.js')
module.hi('Erick')
}
}
Now think about the possibilities along with Object Destructuring Assignment! For example, we are able to easily put only one of those named exports in memory for posterior use:
const { bye } = await import('./something.js')
bye('Erick')
Or maybe grab one of those named exports and rename it to anything else we want:
const { hi: hello } = await import('./something.js')
hello('Erick')
Or even rename the default exported function to something that makes more sense:
const { default: helloWorld } = await import('./something.js')
helloWorld()
Just a last (but no least) note: import()
may looks like a function call, but it isn't a Function
. It's a special syntax that just happens to use parentheses (similar to what happens with super()
). So it's not possible to assign import
to a variable or use things of the Function
prototype, like call
/apply
.