我需要做一些类似的事情:

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

上面的代码不能编译;它抛出SyntaxError:…“import”和“export”只能出现在顶层。

我尝试使用系统。导入如下所示,但我不知道系统来自哪里。是ES6提案最终没有被接受吗?那篇文章中的“程序化API”链接把我扔到了一个废弃的文档页面。


当前回答

我知道这不是问题所要求的,但下面是我在使用vite时使用模拟的方法。我相信我们也可以在webpack和其他产品上做到这一点。

假设我们有两个具有相同接口的库:link.js和link-mock.js,那么:

在我的vite.config.js中

export default defineConfig(({ command, mode }) => {
    
    const cfg = {/* ... */}

    if (process.env.VITE_MOCK == 1) {
        cfg.resolve.alias["./link"] = "./link-mock"; // magic is here!
    }

    return cfg;
}

代码:

import { link } from "./link";

在控制台,我们称之为:

# to use the real link.js
npm run vite

# to use the mock link-mock.js
VITE_MOCK=1 npm run vite

or

包中。json脚本

{
    ....
    "scripts": {
        "dev": "vite",        
        "dev-mock": "VITE_MOCK=1 vite"
    }
}

其他回答

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

你可以:

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的情况下,它需要初始化。

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

let something = null;
let other = null;

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

如果你使用动态导入Webpack模式,重要的区别是:

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(...);
}

看一下这个例子,可以清楚地理解动态导入是如何工作的。

动态模块导入示例

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

JavaScript模块Github

Javascript模块MDN

我可以使用立即调用的函数和require语句来实现这一点。

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

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