azpublic
azpublic

Reputation: 1404

ES6 dynamic imports and instanciation of classes

I'm trying to figure out how to perform dynamic import of classes in ES6 one the server side (node.js with Babel). I would like to have some functionalities similar to what reflection offers in Java. The idea is to import all the classes in a specific folder and instanciate them dynamically.

So for example I could have multiple classes declared in a folder like the one below :

export default class MyClass {

   constructor(somevar) {
       this._somevar = somevar
   }

   //...
   //some more instance level functions here
}

and then somewhere else in my app's code I could have a function that finds out all the classes in a specific folder and tries to instanciate them :

//somewhere else in my app
instanciationFunction(){

   //find all the classes in a specific folder
   var classFiles = glob.sync(p + '/path_to_classes/**/*.js', {
       nodir: true
   });

   _.each(classFiles, async function (file) {
       console.log(file);

       var TheClass = import(file);
       var instance = new TheClass();

       //and then do whatever I want with that new instance

   });
}

I've tried doing it with require but I get errors. Apparently the constructor cant be found.

Any idea would be greatly appreciated.

Thanks

Upvotes: 1

Views: 3632

Answers (3)

user1108319
user1108319

Reputation: 29

I had the same usecase and i managed to dynamically load and instantiate default exported classes using:

const c = import("theClass.js")
const i = new c.default();

using node v16.4.0

Upvotes: 1

roberto tomás
roberto tomás

Reputation: 4687

You need to preprocess with babel, because they are not yet a part of node (for that matter, neither are static imports - node uses require).

https://github.com/airbnb/babel-plugin-dynamic-import-node

steps:

pre

npm i -D babel-cli or npm i -D babel

1

npm i -D babel-plugin-dynamic-import-node

2 .babelrc
{
  "plugins": ["dynamic-import-node"]
}
ready, go!

babel-node test_import.js for babel-cli, or for raw babel:

a (edit) package.json
"scripts": {
  "pretest": "babel test_imports.js -o dist/test_imports.js",
  "test": "node dist/test_imports.js"
//...
b

node test

Upvotes: 1

Joseph
Joseph

Reputation: 119847

ES module definitions are declarative, and the current direction tools are taking is the path where dependencies are determined during parse (via static analysis), waaay before any of the code is executed. This means dynamic and conditional imports go against the said path. It's not like in Node where imports are determined on execution, upon executing require.

If you want dynamic, runtime imports, consider taking a look at SystemJS. If you're familiar with RequireJS, it takes the same concept, but expands it to multiple module formats, including ES6. It has SystemJS.import which appears to do what you want, plus handles the path resolution that you're currently doing.

Alternatively, if your intention is to shed off excess code, consider using Rollup. It will analyze code for you and only include code that's actually used. That way, you don't need to manually do conditional loading.

Upvotes: 1

Related Questions