📜 ⬆️ ⬇️

Node.JS Get rid of require () forever

Analyzing the source codes of past projects, the popularity rating of direct function calls showed that a direct call of require() is found in the code of node-modules almost as often as Array#forEach() . The most annoying thing is that we most often connect the modules "util" , "fs" and "path" , a little less often "url" . The presence of other connected modules depends on the task of the module. Moreover, speaking of the "util" module, it is loaded into the memory of the node-process even if you have never connected it.

In the last article, Node.JS Loading Modules on Demand, I talked about the possibility of automatically loading a module when it first accessed its named link. To be honest, at the time of writing this article, I was not sure that such an approach would not cause the strange behavior of the node-process. But, today I can proudly demandLoad() that demandLoad() has been in production for half a year already. As we just did not drive it ... This is the load testing of a specific process, and the work of demandLoad() in the worker-processes of clusters, and the work of the process under a small load for a long time. Results were compared using demandLoad() and using require() . No significant deviations in comparison were observed.

Today we are not talking about the stability of demandLoad() . If anyone is interested, ask questions in the comments, take screenshots, I can tell you about the methods and tools of testing, other possibilities of using the approach. Today, as follows from the title of the article, we will get rid of those who already get bored with require() in the caps of each node-module.
')
I note in advance that I do not in any way agitate to use the proposed method in production. The practice is stated for familiarization and does not pretend to the status of "true-practice". Loud headline just to attract attention.

Suppose we are working on a project called "mytestsite.com" , and we have it here:

 ~/projects/mytestsite.com 

Create an executable file of our project, for example, at:

 ~/projects/mytestsite.com/lib/bin/server.js 

Inside we will try to call the connected modules without prior require() :

 console.log(util.inspect(url.parse('https://habrahabr.ru/'))); 

Now create the "require-all.js" file somewhere, outside of all projects.
For example, here:

 ~/projects/general/require-all.js 

According to the documentation , all the predefined variables and constants of each node-module are global properties. Accordingly, we can define our own global objects. So we must do with all the modules we use.

Fill require-all.js list of all used modules in all projects:

 //      "util", // ..        "console". //  console.log(),      , //     util.inspect() global.util = require('util'); //      , : demandLoad(global, 'fs', 'fs'); demandLoad(global, 'path', 'path'); demandLoad(global, 'url', 'url'); //      npm-, : demandLoad(global, 'express', 'express'); // , , ,     : demandLoad(global, 'routes', './../mytestsite.com/lib/routes'); //  demandLoad function demandLoad(obj, name, modPath){ //      //       . } 

You can represent the list of modules as an array or map ( Map ), and, for example, walk on it / her in a loop so as not to repeat a line of code with a call to demandLoad() . You can, for example, read the list of used npm-modules from package.json . If, for example, the number of modules used is very high, and you do not want to clutter up the global scope, you can define, for example, an empty object m ( let m = {} ), define m in global ( global['m'] = m ), and already apply demandLoad() to m . As they say, to whom it is more convenient.

Now, it remains only to run this farm. Add the --require key to the node launch (versions> = 4.x):

 node --require ~/projects/general/require-all.js \ ~/projects/mytestsite.com/lib/bin/server.js 

No errors. The script worked as it should:

 Url { protocol: 'https:', slashes: true, auth: null, host: 'habrahabr.ru', port: null, hostname: 'habrahabr.ru', hash: null, search: null, query: null, pathname: '/', path: '/', href: 'https://habrahabr.ru/' } 

If you have many projects, for the convenience of deploying projects, you can create your own require-all.js within each project separately.

 node --require ~/projects/mytestsite.com/lib/require-all.js \ ~/projects/mytestsite.com/lib/bin/server.js 

Extending the latter case, I note, you can even use several such require-all.js at the same time:

 node --require ~/projects/general/require-all.js \ --require ~/projects/mytestsite.com/lib/require-all.js \ ~/projects/mytestsite.com/lib/bin/server.js 

As noted in the comment below , the --require + global bundle can also be used to extend / overload standard node features.

Finally, I repeat from the previous article: If demandLoad() is not defined in our file (1) (whence we call demandLoad() ), but in some file (2), with file (1) and file (2) located in different directories, the last parameter must pass the full path to the module, for example:

 demandLoad(global, 'routes', path.join(__dirname, './../mytestsite.com/lib/routes')); 

Otherwise, that require() that is called from demandLoad() will search for a module relative to the folder where that same file (2) is located with the description of demandLoad() , instead of looking for a module relative to file (1), from where we call demandLoad() .

Thanks for attention. All successful refactoring!

Source: https://habr.com/ru/post/273405/


All Articles