How can I conditionally import an ES6 module?

es6 dynamic import
conditional import python
es6 modules
javascript dynamic import
conditional import typescript
webpack dynamic import
babel dynamic-import
es6 import if exists

I need to do something like:

if (condition) {
    import something from 'something';
}
// ...
if (something) {
    something.doStuff();
}

The above code does not compile; it throws SyntaxError: ... 'import' and 'export' may only appear at the top level.

I tried using System.import as shown here, but I don't know where System comes from. Is it an ES6 proposal that didn't end up being accepted? The link to "programmatic API" from that article dumps me to a deprecated docs page.

We do have dynamic imports proposal now with ECMA. This is in stage 3. This is also available as babel-preset.

Following is way to do conditional rendering as per your case.

if (condition) {
    import('something')
    .then((something) => {
       console.log(something.something);
    });
}

This basically returns a promise. Resolution of promise is expected to have the module. The proposal also have other features like multiple dynamic imports, default imports, js file import etc. You can find more information about dynamic imports here.

Dynamic imports, js file too near the normal module. Empty modules should be literally empty with only class exports, no methods  You can’t import conditionally, but you can do the opposite: export something conditionally. It depends on your use case, so this work around might not be for you. You can do: api.js. import mockAPI from './mockAPI' import realAPI from './realAPI' const exportedAPI = shouldUseMock ? mockAPI : realAPI export default exportedAPI apiConsumer.js

If you'd like, you could use require. This is a way to have a conditional require statement.

let something = null;
let other = null;

if (condition) {
    something = require('something');
    other = require('something').other;
}
if (something && other) {
    something.doStuff();
    other.doOtherStuff();
}

Decreasing Webpack's bundle size with conditional imports, (moduleSpecifier) returns a promise for the module namespace object of the requested module, which is created after fetching, instantiating, and evaluating all of the module's dependencies, as well as the module itself. I think the intent is to enable static analysis as much as possible, and conditionally imported modules break that. Also worth mentioning -- I'm using Babel , and I'm guessing that System is not supported by Babel because the module loader API didn't become an ES6 standard.

You can't import conditionally, but you can do the opposite: export something conditionally. It depends on your use case, so this work around might not be for you.

You can do:

api.js

import mockAPI from './mockAPI'
import realAPI from './realAPI'

const exportedAPI = shouldUseMock ? mockAPI : realAPI
export default exportedAPI

apiConsumer.js

import API from './api'
...

I use that to mock analytics libs like mixpanel, etc... because I can't have multiple builds or our frontend currently. Not the most elegant, but works. I just have a few 'if' here and there depending on the environment because in the case of mixpanel, it needs initialization.

import, node-es-module-loader provides a Node.js executable that supports ES6 module syntax and import() . webpack v1: babel-plugin-dynamic-import  (as suggested in ES6: Conditional & Dynamic Import Statements) ? And is it possible to test a module existence without importing it (basically how to code that isModuleDefined() method?) I have seen those ones as well : ES6 variable import name in node.js? How can I conditionally import an ES6 module?

Looks like the answer is that, as of now, you can't.

http://exploringjs.com/es6/ch_modules.html#sec_module-loader-api

I think the intent is to enable static analysis as much as possible, and conditionally imported modules break that. Also worth mentioning -- I'm using Babel, and I'm guessing that System is not supported by Babel because the module loader API didn't become an ES6 standard.

Understanding ES6 Modules, Imported modules are in strict mode whether you declare them as such load a module conditionally or on demand, you can use a dynamic import instead. Brian Terlson and Microsoft Edge Team: Previewing ES6 Modules  With ES2015 (ES6), with get built-in support for modules in JavaScript. Like with CommonJS, each file is its own module. To make objects, functions, classes or variables available to the outside world it’s as simple as exporting them and then importing them where needed in other files.

require() is a way to import some module on the run time and it equally qualifies for static analysis like import if used with string literal paths. This is required by bundler to pick dependencies for the bundle.

const defaultOne = require('path/to/component').default;
const NamedOne = require('path/to/component').theName;

For dynamic module resolution with complete static analysis support, first index modules in an indexer(index.js) and import indexer in host module.

// index.js
export { default as ModuleOne } from 'path/to/module/one';
export { default as ModuleTwo } from 'path/to/module/two';
export { SomeNamedModule } from 'path/to/named/module';

// host.js
import * as indexer from 'index';
const moduleName = 'ModuleOne';
const Module = require(indexer[moduleName]);

Dynamic import(), 3 Imports and exports must be at the top level #. As explained in more detail later, the structure of ES6 modules is static, you can't conditionally import or export  ES6 modules specification explicitly states import/export statements may only be used at the top level of files. Static imports like this bring about a number of benefits such as first-class support for circular dependencies between modules and (potential) support for macros but it also means you cannot conditionally import modules .

ECMAScript feature: `import()` – dynamically importing ES modules, How to use reference elision to achieve type-safe conditional module ES6 modules specification explicitly states import / export statements  Webpack config: Conditionally import module. Ask Question Asked 4 years, 3 months ago. Webpack with Babel lazy load module using ES6 recommended Import() approach

16. Modules, To import modules we use the new import keyword in ES6, so to import all of the When importing or exporting ES6 Modules you cannot do these conditionally,  As explained in more detail later, the structure of ES6 modules is static, you can’t conditionally import or export things. That brings a variety of benefits. That brings a variety of benefits. This restriction is enforced syntactically by only allowing imports and exports at the top level of a module:

Conditional Imports In TypeScript, Conditional exports provide a way to map to different paths depending on certain conditions. They are supported for both CommonJS and ES module imports. For​  The static import statement is used to import read only live bindings which are exported by another module. MDN will be in maintenance mode for a brief period Tuesday June 2, from around 10:00 AM until no later than 12:00 PM Pacific (in UTC, Tuesday June 2, 5:00 PM to 7:00 PM).

Comments
  • Just import it normally. Your module needs it regardless.
  • I don't really see any reason why you wouldn't just import regardless of the condition. It's not like there's some sort of overhead. In some scenario you need the file, so it's not like there's ever a case where it can be entirely skipped. In that case, just import it unconditionally.
  • My use case: I want to make it easy to have an optional dependency. If the dep is not needed, the user removes it from package.json; my gulpfile then checks if that dependency exists before performing some build steps.
  • Another use case: for testing purposes. I am using webpack and babel to transpile es6 to es5. Projects like webpack-rewire and similar are not to help here - github.com/jhnns/rewire-webpack/issues/12 . One way to set the test doubles OR to remove problematic dependencies could be the conditional import.
  • +1. Being able to use a module in multiple environments where dependencies may or may not work is critical, particularly when modules may refer to dependencies that would only work in the browser (e.g. where webpack is used to convert stylesheets into modules that insert the relevant styles into the DOM when they're imported) but the module also needs to run outside of the browser (e.g. for unit testing).
  • Finally, a real, ES6 answer! Thanks @thecodejack. Actually at stage 3 as of this writing, according to that article now.
  • or if you have just named exports you can destructure: if (condition) { import('something') .then(({ somethingExported }) => { console.log(somethingExported); }); }
  • on Firefox and while running npm run build I still get the error: SyntaxError: ... 'import' and 'export' may only appear at the top level
  • this fails in testing tho, anyone have ideas?
  • That conditional dynamic import function doesn't have the fine grained ability to import only particular elements that "import X from Y" has. In fact that fine grained ability could be even more important in dynamic loading (as opposed to preprocess bundling)
  • I think something and other variables are declsred using const which is block scoped, so the second if condition will throw that something is not defined
  • Would be better to use let and declare the two variables outside the block instead of using 'var' and avoiding the block scope altogether.
  • Does hoisting affect anything in this case? I've run into some problems where hoisting has meant that I've unanticipatedly imported a library when following a pattern close to this if memory serves.