📜 ⬆️ ⬇️

Module loader for node js with support for local modules and load modules on demand

I am a frontend developer and lately I have more and more often used a node, be it using a webpack for building a project, or setting up various gulp tasks. Although I do not have much experience in using a node, over time I have accumulated three things that I would like to improve when working with modules:


To solve all three tasks separately, there are already various modules and solutions, but firstly, they all have, as it seems to me, flaws, and secondly, none of the solutions solves all three problems together.

For example, for loading modules on demand (aka lazy load or load on demand), there is a gulp-load-plugins module. It solves the 1st and 2nd problem, but does not solve the 3rd and has one more drawback - to connect the modules, you need to initialize the gulp-load-plugins module in each file where these modules are needed. You can, of course, do the initialization in a separate file and export the value from the file, but in this case you will have to connect this file using relative or absolute paths.

To solve the 3rd problem about a year ago, support for so-called local modules was added to npm. The bottom line is that
in package.json in dependencies, you need to specify the names of the modules as keys, and in the values ​​- relative paths to the folders of local modules with the prefix “file:”, for example, here is part of the package.json file:
')
"dependencies": { "lodash": "^2.0.0", "core": "file:deep/deep/deep/core", "my-other-module": "file:/my-other-module" } 

At the same time, the folders of local modules must be designed as normal modules, that is, they must contain their package.json and readme.md files. After running npm i, your local modules will be installed in the node_modules folder, just like normal modules. For me, it is extremely inconvenient to put each project file in a separate folder, and also start package.json and readme.md files on it.

In a word, I didn’t find a good solution for the problems I described, maybe I looked badly, but I went through various forums and, after reading various recent articles, came to the conclusion that people are still looking for a good solution to all these problems.

In the end, I decided to write my decision, perhaps my bicycle, about which I want to tell you. How good or bad to judge you. So let me introduce sp-load. Immediately make a reservation, the prefix sp- does not carry any sacred meaning, it is just the first letters of my name and surname and was added not to glorify me, but because the names “load”, “loader” and others were already taken .

So you made npm i sp-load -S in your project. Suppose you have the following contents of the package.json file:

 { "name": "your-project", "version": "1.0.0", "main": "index.js", "dependencies": { "lodash": "^3.10.1", "sp-load": "^1.0.0" }, "devDependencies": { "gulp": "^3.9.0", "webpack": "^1.12.9" }, "_localDependencies": { "core": "./core/core", "some-module": "./deep/deep/deep/deep/deep/deep/deep/some-module" } } 

And you have the following file structure:

 your-project/ node_modules sp-load/ ... gulp/ ... lodash/ ... webpack/ ... package.json core/ core.js deep/ deep/ deep/ deep/ deep/ deep/ deep/ some-module.js gulpfile.js index.js 

What do you need to do to use sp-load in its simplest form? Just one thing, do var $ = require ('sp-load'); inside any file, for example, here is the contents of gulpfile.js:

 'use strict'; var $ = require('sp-load'), webpackConfig = {}; $.gulp.task("webpack", function (callback) { $.webpack(webpackConfig, function (err, stats) { callback(); }); }); 

Content some-module.js:

 'use strict'; function someModuleFuction() { console.log('I\'m some module function call!'); } module.exports = someModuleFuction; 

Core.js content:

 'use strict'; function coreModuleFuction() { console.log('I\'m core module function call!'); } module.exports = coreModuleFuction; 

Content index.js:

 'use strict'; var $ = require('sp-load'); $.someModule(); $.core(); 

As you can see, all that needs to be done is to connect the sp-load module. It returns an object containing a list of modules that will be loaded on demand, that is, the module will be loaded by the node at the first call by the module name, for example, $ .core ().

You also probably noticed the non-standard property "_localDependencies" in package.json. In this property you can define a list of local modules of your project. The keys of the object are the names of the modules, the values ​​are the relative path to the module file (the path is relative to the package.json file).

If you want to refer to modules not as object properties, but as variables, then you can do it as follows (in the example es6 destructuring is used. You can read how to enable es6 capabilities in nodejs in the nodejs documentation):

 'use strict'; var {someModule, core} = require('sp-load'); someModule(); core(); 

Or using es5:

 'use strict'; var $ = require('sp-load'), someModule = $.someModule, core = $.core; someModule(); core(); 

In both of these examples, the modules someModule and core will be loaded during assignment, if you want them to be loaded at the time of their first use (that is, on demand), then refer to the modules as properties of the $ object.

This was the simplest use of sp-load, without any configurations, except for using the "_localDependencies" property in package.json. Now I want to show what settings sp-load supports. In order to configure sp-load, you need to add the property "_sp-load" in package.json. Below is an example of the package.json file, which shows all possible settings with comments about the purpose of each of them:

 { "name": "your-project", "version": "1.0.0", "main": "index.js", "dependencies": { "lodash": "^3.10.1", "sp-load": "^1.0.0" }, "devDependencies": { "gulp": "^3.9.0", "webpack": "^1.12.9" }, "_localDependencies": { "core": "./core/core", "some-module": "./deep/deep/deep/deep/deep/deep/deep/some-module" }, "_sp-load": { /*   true,      camel case. ,  $['some-module']  $.someModule.   - true. */ "camelizing": false, /*       . ,  $.lodash     $._ */ "renaming": { "lodash": "_", "gulp": "supergulp" }, /*       ,   .  -  ,  - ,     .     - gulp ,       gulp-, , gulp-concat,        $.concat  $.gulpConcat. */ "replacing": { "/^gulp-/": "" } } } 

If you do not want to clutter up the package.json file, then put the sp-load settings and the list of local modules in the _sp-load.json file, which should be in the same folder as package.json, that is:

 yourProject/ package.json _sp-load.json 

Here is an example of the contents of the _sp-load.json file:

 { "_localDependencies": { "core": "./core/core", "some-module": "./deep/deep/deep/deep/deep/deep/deep/some-module" }, "_sp-load": { "camelizing": false, "renaming": { "lodash": "_", "gulp": "supergulp" }, "replacing": { "/^gulp-/": "" } } } 

And the last thing I haven't mentioned yet. When you make $ = require ('sp-load') ;, the $ object contains the property "_spModulesList" in its prototype. This property contains the object, where keys are the names of the modules, and values ​​are the absolute path to the module file. Here is an example of the contents of this object:

 { "lodash": "lodash", "sp-load": "sp-load", "gulp": "gulp", "webpack": "webpack", "core": "D://your-project//core//core.js", "some-module": "D://your-project//deep//deep//deep//deep//deep//deep//deep//some-module.js" } 

What is it useful for? For example, when using System.js loader.

Perhaps that's all. Before publishing the module on npmjs.com, I tested it, but I haven’t used it in a real project, so if there are any errors, I will be glad if you report them.

Link to the module itself: sp-load .

PS: Maybe someone will tell you how to remove a published module from npmjs.com? Nowhere did you find how to do this, and npm unpublish removes the module, but with the subsequent npm publish you have to increase the version of the module. npm swears that the current version is already registered.

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


All Articles