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

eri*_*oco 167 javascript module ecmascript-6

我需要做类似的事情:

if (condition) {
    import something from 'something';
}
// ...
if (something) {
    something.doStuff();
}
Run Code Online (Sandbox Code Playgroud)

上面的代码没有编译; 它抛出SyntaxError: ... 'import' and 'export' may only appear at the top level.

我试着用System.import如图所示这里,但我不知道在哪里System的来了.是不是最终被接受的ES6提案?该文章中"programmatic API"的链接将我转储到已弃用的文档页面.

the*_*ack 115

我们现在有ECMA的动态进口提案.这是在第3阶段.这也可以作为babel预设.

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

if (condition) {
    import('something')
    .then((something) => {
       console.log(something.something);
    });
}
Run Code Online (Sandbox Code Playgroud)

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

  • 最后,一个真实的ES6答案!谢谢@thecodejack.实际上在撰写本文时的第3阶段,现在根据那篇文章. (10认同)
  • 或者如果你刚刚命名了导出,你可以解构:`if(condition){import('something').then(({somethingExported})=> {console.log(somethingExported);}); }` (5认同)
  • 在Firefox上运行`npm run build`时我仍然得到错误:`SyntaxError:...'import'和'export'可能只出现在顶层 (3认同)
  • @stackjlei:此功能还不是 JavaScript 标准的一部分,它只是第 3 阶段的提案!但是,它已经在许多较新的浏览器中实现,请参阅 https://caniuse.com/#feat=es6-module-dynamic-import。 (3认同)
  • 该条件动态导入函数不具备仅导入“从 Y 导入 X”所具有的特定元素的细粒度能力。事实上,细粒度能力在动态加载中可能更为重要(相对于预处理捆绑) (2认同)

Bap*_*els 89

如果您愿意,可以使用require.这是一种具有条件require语句的方法.

let something = null;
let other = null;

if (condition) {
    something = require('something');
    other = require('something').other;
}
if (something && other) {
    something.doStuff();
    other.doOtherStuff();
}
Run Code Online (Sandbox Code Playgroud)

  • 需要指出的是,`require()`不是标准JavaScript的一部分-它是Node.js中的内置函数,因此仅在该环境中有用。OP没有提供使用Node.js的指示。 (5认同)
  • 2020 编辑:静态和动态导入现在都是标准 JS 产品的一部分。 (2认同)

Kev*_*Kev 43

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

你可以做:

api.js

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

const exportedAPI = shouldUseMock ? mockAPI : realAPI
export default exportedAPI
Run Code Online (Sandbox Code Playgroud)

apiConsumer.js

import API from './api'
...
Run Code Online (Sandbox Code Playgroud)

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

  • 我认为这个解决方案会导致加载不需要的模块,因此不是最佳解决方案. (29认同)
  • 如答案中所述,这是一种解决方法.那时,根本没有解决方案.ES6进口不是动态的,这是设计的.ES6动态导入功能提议(在当前接受的答案中描述)可以实现.JS正在发展:) (3认同)

Leo*_*ele 10

2020 更新

您现在可以将import关键字作为函数(即import())调用以在运行时加载模块。

例子:

const mymodule = await import(modulename);
Run Code Online (Sandbox Code Playgroud)

或者:

import(modulename)
    .then(mymodule => /* ... */);
Run Code Online (Sandbox Code Playgroud)

请参阅https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#Dynamic_Imports

  • ❤️ 让 StackOverflow 保持最新状态。 (13认同)

eri*_*oco 9

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

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

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

  • 2020 编辑:静态和动态导入现在都是标准 JS 产品的一部分。 (2认同)

Sol*_*olo 7

如果您使用动态导入 Webpack 模式,则重要区别eager

if (normalCondition) {
  // this will be included to bundle, whether you use it or not
  import(...);
}

if (process.env.SOMETHING === 'true') {
  // this will not be included to bundle, if SOMETHING is not 'true'
  import(...);
}
Run Code Online (Sandbox Code Playgroud)

  • 但“import”返回一个承诺。 (2认同)

小智 7

JS 有条件导入和导出

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

export default value
Run Code Online (Sandbox Code Playgroud)