0

I am using node --experimental-modules test.mjs (NodeJs v11.9.0).

There are many options to implement the same class, and I need to swith by terminal,

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';
}

ERROR on import MyClass: Unexpected identifier

PS: working fine when using isolated import MyClass from './MyClass-v3.mjs';.


NOTE: const MyClass = require('./MyClass-v3.mjs') not works with modern Javascript. (ReferenceError: require is not defined). The file have only a class definition,

export default class MyClass { ... }

PS: there are nothing like C_preprocessor for NodeJs? An old pre-compiler (with some argv access) will be fine here.

16
  • 1
    Hi. Probably you need to use Factory pattern en.wikipedia.org/wiki/Factory_method_pattern Commented Mar 3, 2019 at 11:35
  • Hi @VladKosko, make sense... What the best way to implement it with Node? No easy way to dynamic loading? My code is also a kind of proxy pattern. Commented Mar 3, 2019 at 11:39
  • The import statement is only allowed at the top level of modules. To import anywhere else use require. Commented Mar 3, 2019 at 13:48
  • 1
    You will need a dynamic import for this, you cannot put an import declaration inside a switch case. Not sure though whether node already supports import(). Commented Mar 3, 2019 at 14:52
  • 1
    @PeterKrauss You cannot do synchronous dynamic imports with ES6 modules. Given that this code seems to be located in your main.js, doing it asynchronously should not be a problem. Commented Mar 3, 2019 at 16:12

2 Answers 2

2
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;

You could also write an index file with all the classes and do an import * as classes from 'classes.mjs';.

Sign up to request clarification or add additional context in comments.

2 Comments

Hi, is a valid solution because it works (!), but it is in the opposite of the "import only necessary" philosophy... An old pre-compiler solution will be better.
You can not do a precompiler solution if you don't know at compile time which class you want. So all modules have to be available at runtime. But if you want a precompiler, this is probably the closest you get: webpack.js.org/contribute/writing-a-loader Use can use codeshift for the transformation: github.com/facebook/jscodeshift
0

Modern Javascript (ES6+) implementations are under construction, some syntax are working with NodeJS (node --experimental-modules) and good browsers, other not.

This is the only way to do without cost of "load all" (see @Markus solution), but with the cost of non-global import, needs an ugly block to define scope and assyncronous operation... First step is to understand the basic impor block syntax:

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

Them, putting all together, the argv selection and the optional imports.

Solution

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: some of the magic (no rational) is to use ({default: MyClass}) instead (MyClass).


Thanks

To @Bergi (!), for explain this solution (see question comments).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.