Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to cause the JS engine to load a .js file without explicitly importing something from it?

Maybe I'm trying to do something silly, but I've got a web application (Angular2+), and I'm trying to build it in an extensible/modular way. In particular, I've got various, well, modules for lack of a better term, that I'd like to be able to include or not, depending on what kind of deployment is desired. These modules include various functionality that is implemented via extending base classes.

To simplify things, imagine there is a GenericModuleDefinition class, and there are two modules - ModuleOne.js and ModuleTwo.js. The first defines a ModuleOneDefinitionClass and instantiate an exported instance ModuleOneDefinition, and then registers it with the ModuleRegistry. The second module does an analogous thing.

(To be clear - it registers the ModuleXXXDefinition object with the ModuleRegistry when the ModuleXXX.js file is run (e.g. because of some other .js file imports one of its exports). If it is not run, then clearly nothing gets registered - and this is the problem I'm having, as I describe below.)

The ModuleRegistry has some methods that will iterate over all the Modules and call their individual methods. In this example, there might be a method called ModuleRegistry.initAllModules(), which then calls the initModule() method on each of the registered Modules.

At startup, my application (say, in index.js) calls ModuleRegistry.initAllModules(). Obviously, because index.js imports the exported ModuleRegistry symbol, this will cause the ModuleRegistry.js code to get pulled in, but since none of the exports from either of the two Module .js files is explicitly referenced, these files will not have been pulled in, and so the ModuleOneDefinition and ModuleTwoDefinition objects will not have been instantiated and registered with the ModuleRegistry - so the call to initAllModules() will be for naught.

Obviously, I could just put meaningless references to each of these ModuleDefinition objects in my index.js, which would force them to be pulled in, so that they were registered by the time I call initAllModules(). But this requires changes to the index.js file depending on whether I want to deploy it with ModuleTwo or without. I was hoping to have the mere existence of the ModuleTwo.js be enough to cause the file to get pulled in and the resulting ModuleTwoDefinition to get registered with the ModuleRegistry.

Is there a standard way to handle this kind of situation? Am I stuck having to edit some global file (either index.js or some other file it references) so that it has information about all the included Modules so that it can then go and load them? Or is there a clever way to cause JavaScript to execute all the .js files in a directory so that merely copying the files it would be enough to get them to load at startup?

like image 399
Doug Avatar asked May 23 '18 10:05

Doug


People also ask

Can I use require instead of import?

NOTE: You must note that you can't use require and import at the same time in your node program and it is more preferred to use require instead of import as you are required to use the experimental module flag feature to run import program.

How do I include an external JS file in another JavaScript file?

To include an external JavaScript file, we can use the script tag with the attribute src . You've already used the src attribute when using images. The value for the src attribute should be the path to your JavaScript file.

Can we use import instead of require in node JS?

You can now start using modern ES Import/Export statements in your Node apps without the need for a tool such as Babel.

How do you get a value from one JS file to another JS file?

Answer: Use the export and import Statement Since ECMAScript 6 (or ES6) you can use the export or import statement in a JavaScript file to export or import variables, functions, classes or any other entity to/from other JS files.


1 Answers

a clever way to cause xxJavaScriptxx Node.js to execute all the .js files in a directory:

var fs = require('fs')  // node filesystem 
var path = require('path') // node path 

function hasJsExtension(item) {
  return item != 'index.js' && path.extname(item) === '.js'
}

function pathHere(item) {
  return path.join('.', item)
}

fs.readdir('./', function(err, list) {
  if (err) return err
  list.filter(hasJsExtension).map(pathHere).forEach(require) // require them all
})

Angular is pretty different, all the more if it is ng serve who checks if your app needs a module, and if so serves the corresponding js file, at any time needed, not at first load time.

In fact your situation reminds me of C++ with header files Declaration and cpp files with implementation, maybe you just need a defineAllModules function before initAllModules.

Another way could be considering finding out how to exclude those modules from ng-serve, and include them as scripts in your HTML before the others, they would so be defined (if present and so, served), and called by angular if necesary, the only cavehat is the error in the console if one script tag is not fetched, but your app will work anyway, if it supposed to do so.

But anyway, it would be declaring/defining those modules somewhere in ng-serve and also in the HTML.

In your own special case, and not willing to under-evalute ng-serve, but is the total js for your app too heavy to be served at once? (minified and all the ...), since the good-to-go solution may be one of the many tools to build and rebuild your production all.js from your dev js folder at will, or like you said, with a drag&drop in your folder.

Such tool is, again, server-side, but even if you only can push/FTP your javascript, you could use it in your prefered dev environment and just push your new version. To see a list of such tools google 'YourDevEnvironment bundle javascript'.

like image 69
lucchi Avatar answered Nov 10 '22 00:11

lucchi