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

时间:2022-05-24 15:22:37

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.

上面的代码没有编译;抛出SyntaxError:...'import'和'export'可能只出现在顶层。

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.

我尝试使用System.import,如图所示,但我不知道System来自何处。是不是最终被接受的ES6提案?该文章中“programmatic API”的链接将我转储到已弃用的文档页面。

5 个解决方案

#1


45  

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

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

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.

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

#2


60  

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

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

let something = null;
let other = null;

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

#3


25  

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

api.js

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

const exportedAPI = shouldUseMock ? mockAPI : realAPI
export default exportedAPI

apiConsumer.js

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.

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

#4


9  

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

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

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

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.

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

#5


-1  

obscuring it in an eval worked for me, hiding it from the static analyzer ...

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

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

#1


45  

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

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

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.

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

#2


60  

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

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

let something = null;
let other = null;

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

#3


25  

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

api.js

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

const exportedAPI = shouldUseMock ? mockAPI : realAPI
export default exportedAPI

apiConsumer.js

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.

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

#4


9  

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

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

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

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.

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

#5


-1  

obscuring it in an eval worked for me, hiding it from the static analyzer ...

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

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