【问题标题】:How to dynamically select module with modern nodeJS?如何使用现代 nodeJS 动态选择模块?
【发布时间】:2019-03-03 11:30:55
【问题描述】:

我正在使用node --experimental-modules test.mjs (NodeJs v11.9.0)。

实现同一个类有很多选择,需要终端切换,

switch (process.argv[2]) {
  case 'a':
    import MyClass from './MyClass-v1.mjs'; break;
  case 'b':
    import MyClass from './MyClass-v2.mjs'; break;
  default:
    import MyClass from './MyClass-v3.mjs';
}

import MyClass 上的错误:意外的标识符

PS:使用 isolated import MyClass from './MyClass-v3.mjs'; 时工作正常。


注意:const MyClass = require('./MyClass-v3.mjs') 不适用于现代 Javascript。 (ReferenceError: 要求未定义)。该文件只有一个类定义,

export default class MyClass { ... }

PS:对于 NodeJs,没有像 C_preprocessor 这样的东西吗?旧的预编译器(带有一些 argv 访问权限)在这里就可以了。

【问题讨论】:

  • 嗨。可能你需要使用工厂模式en.wikipedia.org/wiki/Factory_method_pattern
  • 嗨@VladKosko,有道理...用Node实现它的最佳方法是什么?没有简单的动态加载方法?我的代码也是一种proxy pattern
  • import 语句只允许在模块的顶层。要导入其他任何地方,请使用require
  • 为此您需要dynamic import,您不能将导入声明放在开关盒中。不确定节点是否已经支持import()
  • @PeterKrauss 您不能使用 ES6 模块进行同步动态导入。鉴于此代码似乎位于您的 main.js 中,异步执行它应该不是问题。

标签: node.js ecmascript-6


【解决方案1】:
import ClassV1 from './MyClass-v1.mjs';
import ClassV2 from './MyClass-v2.mjs'; 
import ClassV3 from './MyClass-v3.mjs';

const classes = {
  a: ClassV1,
  b: ClassV2
}

const Class = classes[process.argv[2]] || ClassV2;

您还可以编写一个包含所有类的索引文件并执行import * as classes from 'classes.mjs';

【讨论】:

  • 嗨,这是一个有效的解决方案,因为它可以工作(!),但它与“只需要导入”的理念相反......旧的预编译器解决方案会更好。跨度>
  • 如果你在编译时不知道你想要哪个类,你就不能做一个预编译器解决方案。所以所有模块都必须在运行时可用。但是如果你想要一个预编译器,这可能是你得到的最接近的:webpack.js.org/contribute/writing-a-loader 使用可以使用 codeshift 进行转换:github.com/facebook/jscodeshift
【解决方案2】:

现代 Javascript (ES6+) 实现正在建设中,一些语法适用于 NodeJS (node --experimental-modules) 和良好的浏览器,其他没有。

这是没有“全部加载”成本的唯一方法(请参阅@Markus 解决方案),但是由于非全局导入的成本,需要一个丑陋的块来定义范围和异步操作......第一步是了解基本的import块语法:

import('./MyClass-v3.mjs').then(({default: MyClass}) => {
    // can use MyClass only here in this block
    let x = new MyClass();
    console.log("DEBUG=",x);
});

它们,将 argv 选择和可选导入放在一起。

解决方案

const classes = {
  a: './MyClass-v1.mjs'
  ,b: './MyClass-v3.mjs'
  ,c: './MyClass-v3.mjs'
};
import(classes[process.argv[2]] || classes.c ).then(({default: MyClass}) => {
    let x = new MyClass();
    console.log("DEBUG=",x);
});

PS:一些魔法(不合理)是使用({default: MyClass}) 而不是(MyClass)


谢谢

致@Bergi (!),解释这个解决方案(见问题 cmets)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-22
    • 2023-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-01
    相关资源
    最近更新 更多