如何有条件地导入ES6模块?

时间:2016-04-01 23:44:59

标签: javascript module ecmascript-6

我需要做类似的事情:

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

以上代码无法编译;它抛出SyntaxError: ... 'import' and 'export' may only appear at the top level

我尝试使用显示hereSystem.import,但我不知道System来自哪里。是ES6提案还没有被接受吗?指向"程序化API"的链接从那篇文章中我转发到deprecated docs page

11 个答案:

答案 0 :(得分:86)

我们现在有ECMA的动态导入提案。这是在第3阶段。这也可以babel-preset

以下是根据您的情况进行条件渲染的方法。

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

这基本上是一个承诺。承诺的解决方案预计将有模块。该提案还具有其他功能,如多个动态导入,默认导入,js文件导入等。您可以找到有关dynamic imports here的更多信息。

答案 1 :(得分:83)

如果您愿意,可以使用require。这是一种获得条件需求声明的方法。

let something = null;
let other = null;

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

答案 2 :(得分:37)

你无法有条件地进口,但你可以做相反的事情:有条件地出口。这取决于您的使用案例,因此这可能不适合您。

你可以这样做:

api.js

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

const exportedAPI = shouldUseMock ? mockAPI : realAPI
export default exportedAPI

apiConsumer.js

import API from './api'
...

我用它来模拟像mixpanel这样的分析库...因为我目前不能有多个构建或我们的前端。不是最优雅,但有效。我只是有一些' if'这里和那里取决于环境,因为在mixpanel的情况下,它需要初始化。

答案 3 :(得分:9)

看起来答案是,截至目前,你不能。

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

我认为目的是尽可能地启用静态分析,并且有条件导入的模块会破坏它。另外值得一提的是 - 我使用Babel,并且我猜测Babel不支持System,因为模块加载器API没有成为ES6标准。

答案 4 :(得分:2)

使用动态导入Webpack模式,时的重要区别:

eager

答案 5 :(得分:1)

require()是一种在运行时导入某些模块的方法,如果与字符串文字路径一起使用,它也同样适用于import等静态分析。捆绑程序需要此选项来选择捆绑程序的依赖项。

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

要获得具有完整静态分析支持的动态模块解析,请在索引器(index.js)中首先建立索引模块,然后在主机模块中导入索引器。

// 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]);

答案 6 :(得分:0)

在为我工作的eval中隐藏它,将其隐藏在静态分析器中......

if (typeof __CLI__ !== 'undefined') {
  eval("require('fs');")
}

答案 7 :(得分:0)

我能够使用立即调用的函数并需要require语句来实现这一点。

const something = (() => (
  condition ? require('something') : null
))();

if(something) {
  something.doStuff();
}

答案 8 :(得分:0)

请看此示例,以清楚地了解动态导入的工作原理。

Dynamic Module Imports Example

要对导入和导出模块有基本的了解。

JavaScript modules Github

Javascript Modules MDN

答案 9 :(得分:0)

不,你不能!

但是,遇到这个问题应该使您重新思考如何组织代码。

  

在ES6模块之前,我们有CommonJS模块,它们使用require()语法。这些模块是“动态的”,这意味着我们可以根据代码中的条件导入新模块。 -来源:https://bitsofco.de/what-is-tree-shaking/

我猜想他们放弃对ES6的支持的原因之一是编译它非常困难或不可能的事实。

答案 10 :(得分:0)

JS中有条件的导入导出

const value = (
    await import(`${condtion ? `./file1.js` : `./file2.js`}`)
).default

export default value