Nodejs - Create modules from string with the npm package 'module' - node.js

I want to load a custom module using the npm package 'module', to be able to require it like any other local folder that exports something.
I cannot find any documentation on the use of the package https://www.npmjs.com/package/module
I tried to use it without any documentation on it, but i simply cannot as i dont understand how you use it.
let myFunction = module.wrap(`module.exports = () => console.log("hej")`);```

Honestly, I've never read documentation about this but I've been using Node.js for years so I'll explain how I import modules. Given a project that has the files app.js and mod1.js and the subfolder utils with the file mod2.js, you could do something like this:
prj/mod1.js
module.exports = {
test: "testing"
}
prj/utils/mod2.js
module.exports = () => {
console.log("testing");
}
prj/app.js
var mod1 = require("mod1"),
mod2 = require("utils/mod2");
console.log(mod1.test);
mod2();

I think you are trying to create a module of your own to be able to use it at multiple places within your project ( correct me if I am wrong).
SO you can do that like :
In utils/custom.js
module.exports = {
logThis: "Hi"
}
OR
var a={
logThis:function (){
console.log('HI')
}
module.exports=a;
And then in the file where you want to access this :
In app.js
let custom=require('./utils/custom.js')

Related

Resolving nodejs modules from other than node_modules location, is it possible?

For example, when I need a module located inside node_modules I can write const module = require('module') or import module from 'module'. If the module located in another location I need to write const module = require('../location/module'), etc...
This behavior not always desired, for example, If I have examples that I want a user will be able to copy/paste and run, and also to run this example from the project folder itself.
Can this be achieved?
I don't understand why I get downvoted, but I ended up to write the following wrapper which does the job:
const customRequire = function (moduleName, path) {
let module
try {
module = require(moduleName)
} catch (e) {
try {
module = require(`${path}/${moduleName}`)
} catch (e1) {
throw Error(`module ${moduleName} on path ${path} wasn't found`)
}
}
return module
}
Now if you copy/paste this code it will work. And if you will run it within the project where required modules defined and not located in node_modules it will work too.
The solution above work for the CommonJS module system, for ES6 you need to use the function import, to dynamically import modules
import('/modules/my-module.js')
.then((module) => {
// Do something with the module.
});

Exported object is empty

I'm struggling since 2 days on something that shouldn't block me.
Basically, I'm building a nodeJS app that uses Express.
In my main file (located in my root folder), i'm exporting some variables/consts, for the purpose of the example I replaced them like this :
// ./index.js
const test = 'test'
module.exports = { test }
... some express initialization/routers
I then have another file that I want to use the "test" variable in, so I require my main file :
// ./aaa/bbb/ccc/test.js
const { test } = require('../../../index);
const myRouter = require('express').Router();
myRouter.get('/', function (req, res){
console.log(test) // undefined
})
I don't really know why it would be undefined as I correctly exported it, and "imported" it through my require statement.
I also tried "consoling" the whole object that I should receive, and it's empty : {}
EDIT : my "main" script that i'm executing is indeed index.js, but I highly doubt it's the reason of the problem
I can't really find out what could be the problem, and I need to export some variable to access them in my project
Thanks!
I think you did it right. The problem may be that es6 features are not acceptable on your node version. Try it like: module.exports = { test:test }.

How Do I create a NodeJS Module?

I have read the details on NodeJS site : https://nodejs.org/api/modules.html. I don't understand how modules work, and what are the minimal steps for creating a module, and how npm can help me.
How can I create a module?
How do I use a module?
What does putting it on npm mean?
Note: this is a self answered question, with the purpose of sharing knowledge as a canonical.
You can create a NodeJS module using one line of code:
//mymodule.js
module.exports = 3;
Then you can load the module, by using require:
//app.js
require('./mymodule.js')
I added './' because it is a module of one file. We will cover it later.
Now if you do for example:
var mymodule = require('./mymodule.js');
console.log(mymodule); // 3
You can replace the number 3, with a function, for example:
//mymodule.js:
module.exports = function () {
console.log('function inside the module');
};
Then you can use it:
var mymodule = require('./mymodule.js');
mymodule();
Private variables:
Every variable you define inside A module will be defined only inside it:
//mymodule.js
var myPrivateVariable = 3;
publicVariable = 5; // Never user global variables in modules
//It's bad-pracrtice. Always add: var.
module.exports = function() {
// Every function of the module can use the private variables
return myPrivateVariable++
};
//app.js
var mymodule = require('./mymodule.js');
console.log(mymodule()); // return 3
console.log(mymodule()); // return 4
Reuse modules:
One more thing you need to know about NodeJS modules, is that if you use the same module twice(require it), it will return the same instance, it will not run in twice.
for example:
//app.js
var mymodule1 = require('./mymodule.js');
var mymodule2 = require('./mymodule.js');
console.log(mymodule1()); //return 3
console.log(mymodule2()); //return 4 (not 3)
console.log(mymodule1()); //return 5
As you see in the example below, that private variable is shared between all the instances of the module.
A module package
If your module contain more than one file, or you want to share the module with others, you have to create the module in separate folder, and create a package.json file for the module.
npm init will create package.json file for you.
For modules, there are 3 required parts:
package.json
{
"name" : "You module name",
"version" : "0.0.3"
}
Now, you can publish the module, using npm publish. I recommend you publish all your modules to github as well, then the module will be connected to your github page.
What you publish to NPM will be accessible by everyone. So never publish modules that contain private data. For that you can use private npm modules.
Next steps
Modules can return more than one function or one variable. See this samples in which we return an object.
module.exports.a = function() {
// ..
};
module.exports.b = function() {
// ..
};
// OR
myObj = {
a:3,
b:function() {
return this.a;
}
};
module.exports = myObj;
More info:
Read about package.json files
Versioning in you modules best practice
More best practive for NodeJS modules
Private modules, using private npm
Related Questions:
What is the purpose of Node.js module.exports and how do you use it?
module.exports vs exports in Node.js
Creating module in node.js is pretty simple!!!
You may consider module as a set of functionalities you can use in other code by simply just requiring it.
for eg:Consider a file functional.js having the content:
function display(){
console.log('i am in a display function');
}
module.exports = display;
Now just require it in any other module like:
var display = require('./functional');
display()
Output:i am in a display function
Similarly you can do:
var exports = module.exports = {};
exports.display = function(){
console.log('i am in the display function');
}
or you do the same for objects like:
var funObj = {
hello:function(){
console.log('hello function');
},
display:function(){
console.log('display function');
}
};
module.exports = funObj;
There are two main ways for wiring modules. One of them is using hard coded dependencies, explicitly loading one module into another using a require call. The other method is to use a dependency injection pattern, where we pass the components as a parameter or we have a global container (known as IoC, or Inversion of Control container), which centralizes the management of the modules.
We can allow Node.js to manage the modules life cycle by using hard coded module loading. It organizes your packages in an intuitive way, which makes understanding and debugging easy.
Dependency Injection is rarely used in a Node.js environment, although it is a useful concept. The DI pattern can result in an improved decoupling of the modules. Instead of explicitly defining dependencies for a module, they are received from the outside. Therefore they can be easily replaced with modules having the same interfaces.
Let’s see an example for DI modules using the factory pattern:
class Car {
constructor (options) {
this.engine = options.engine
}
start () {
this.engine.start()
}
}
function create (options) {
return new Car(options)
}
module.exports = create

Namespaces in node.js with require

I am playing around and learning about vows with a personal project. This is a small client side library, with testing done in vows. Therefore, I must build and test a file that is written like this:
(function(exports) {
var module = export.module = { "version":"0.0.1" };
//more stuff
})(this);
In my testing (based off of science.js, d3, etc.) requires that module like so:
require("../module");
I continued to get a "module not defined error" when trying to run the tests, so I went to a repl and ran:
require("../module")
and it returned:
{ module: { version: "0.0.1" } }
I realize I could do something like:
var module = require("../module").module;
but feel like I am creating a problem by doing it that way, especially since the libraries that I based this project on are doing it in the format I described.
I would like for my project to behave similar to those which I based it off of, where:
require("../module");
creates a variable in this namespace:
module.version; //is valid.
I have seen this in a variety of libraries, and I am following the format and thought process to the T but believe I might be missing something about require behavior I don't know about.
There is no problem creating it this way. Modules define what they return in the module.exports object. By the way, you don't actually need self executing functions (SEF), there is no global leakage like in browsers :-)
Examples
module1.js:
module.exports = {
module: { 'version': '0.1.1' }
};
main.js:
var module1 = require( './module1.js' );
// module1 has what is exported in module1.js
Once you've understood how this works, you can easily export the version number right away if you want to:
module1.js:
module.exports = '0.1.1';
main.js:
var module1 = require( './module1.js' );
console.log( module1 === '0.1.1' ); // true
Or if you want some logic, you can easily extend your module1.js file like this:
module.exports = ( function() {
// some code
return version;
} () ); // note the self executing part :-)
// since it's self executed, the exported part
// is what's returned in the SEF
Or, as many modules do, if you want to export some utility functions (and keep others "private"), you could do it like this:
module.exports = {
func1: function() {
return someFunc();
},
func2: function() {},
prop: '1.0.0'
};
// This function is local to this file, it's not exported
function someFunc() {
}
So, in main.js:
var module1 = require( './module1.js' );
module1.func1(); // works
module1.func2(); // works
module1.prop; // "1.0.0"
module1.someFunc(); // Reference error, the function doesn't exist
Your special case
About your special case, I wouldn't recommend doing it like they're doing.
If you look here: https://github.com/jasondavies/science.js/blob/master/science.v1.js
You see that they're not using the var keyword. So, they're creating a global variable.
This is why they can access it once they require the module defining the global variable.
And by the way, the exports argument is useless in their case. It's even misleading, since it actually is the global object (equivalent of window in browsers), not the module.exports object (this in functions is the global object, it'd be undefined if strict mode were enabled).
Conclusion
Don't do it like they're doing, it's a bad idea. Global variables are a bad idea, it's better to use node's philosophy, and to store the required module in a variable that you reuse.
If you want to have an object that you can use in client side and test in node.js, here is a way:
yourModule.js:
// Use either node's export or the global object in browsers
var global = module ? module.exports : window.yourModule;
( function( exports ) {
var yourModule = {};
// do some stuff
exports = yourModule;
} ( global ) );
Which you can shorten to this in order to avoid creating the global variable:
( function( exports ) {
var yourModule = {};
// do some stuff
exports = yourModule;
} ( module ? module.exports : window.yourModule ) );
This way, you can use it like this on the client-side:
yourModule.someMethod(); // global object, "namespace"
And on the server side:
var yourModule = require( '../yourModule.js' );
yourModule.someMethod(); // local variable :-)
Just FYI, .. means "parent directory". This is the relative path of where to get the module. If the file were in the same directory, you'd use ..

Can I load multiple files with one require statement?

maybe this question is a little silly, but is it possible to load multiple .js files with one require statement? like this:
var mylib = require('./lib/mylibfiles');
and use:
mylib.foo(); //return "hello from one"
mylib.bar(): //return "hello from two"
And in the folder mylibfiles will have two files:
One.js
exports.foo= function(){return "hello from one";}
Two.js
exports.bar= function(){return "hello from two";}
I was thinking to put a package.json in the folder that say to load all the files, but I don't know how. Other aproach that I was thinking is to have a index.js that exports everything again but I will be duplicating work.
Thanks!!
P.D: I'm working with nodejs v0.611 on a windows 7 machine
First of all using require does not duplicate anything. It loads the module and it caches it, so calling require again will get it from memory (thus you can modify module at fly without interacting with its source code - this is sometimes desirable, for example when you want to store db connection inside module).
Also package.json does not load anything and does not interact with your app at all. It is only used for npm.
Now you cannot require multiple modules at once. For example what will happen if both One.js and Two.js have defined function with the same name?? There are more problems.
But what you can do, is to write additional file, say modules.js with the following content
module.exports = {
one : require('./one.js'),
two : require('./two.js'),
/* some other modules you want */
}
and then you can simply use
var modules = require('./modules.js');
modules.one.foo();
modules.two.bar();
I have a snippet of code that requires more than one module, but it doesn't clump them together as your post suggests. However, that can be overcome with a trick that I found.
function requireMany () {
return Array.prototype.slice.call(arguments).map(function (value) {
try {
return require(value)
}
catch (event) {
return console.log(event)
}
})
}
And you use it as such
requireMany("fs", "socket.io", "path")
Which will return
[ fs {}, socketio {}, path {} ]
If a module is not found, an error will be sent to the console. It won't break the programme. The error will be shown in the array as undefined. The array will not be shorter because one of the modules failed to load.
Then you can bind those each of those array elements to a variable name, like so:
var [fs, socketio, path] = requireMany("fs", "socket.io", "path")
It essentially works like an object, but assigns the keys and their values to the global namespace. So, in your case, you could do:
var [foo, bar] = requireMany("./foo.js", "./bar.js")
foo() //return "hello from one"
bar() //return "hello from two"
And if you do want it to break the programme on error, just use this modified version, which is smaller
function requireMany () {
return Array.prototype.slice.call(arguments).map(require)
}
Yes, you may require a folder as a module, according to the node docs. Let's say you want to require() a folder called ./mypack/.
Inside ./mypack/, create a package.json file with the name of the folder and a main javascript file with the same name, inside a ./lib/ directory.
{
"name" : "mypack",
"main" : "./lib/mypack.js"
}
Now you can use require('./mypack') and node will load ./mypack/lib/mypack.js.
However if you do not include this package.json file, it may still work. Without the file, node will attempt to load ./mypack/index.js, or if that's not there, ./mypack/index.node.
My understanding is that this could be beneficial if you have split your program into many javascript files but do not want to concatenate them for deployment.
You can use destructuring assignment to map an array of exported modules from require statements in one line:
const requires = (...modules) => modules.map(module => require(module));
const [fs, path] = requires('fs', 'path');
I was doing something similar to what #freakish suggests in his answer with a project where I've a list of test scripts that are pulled into a Puppeteer + Jest testing setup. My test files follow the naming convention testname1.js - testnameN.js and I was able use a generator function to require N number of files from the particular directory with the approach below:
const fs = require('fs');
const path = require('path');
module.exports = class FilesInDirectory {
constructor(directory) {
this.fid = fs.readdirSync(path.resolve(directory));
this.requiredFiles = (this.fid.map((fileId) => {
let resolvedPath = path.resolve(directory, fileId);
return require(resolvedPath);
})).filter(file => !!file);
}
printRetrievedFiles() {
console.log(this.requiredFiles);
}
nextFileGenerator() {
const parent = this;
const fidLength = parent.requiredFiles.length;
function* iterate(index) {
while (index < fidLength) {
yield parent.requiredFiles[index++];
}
}
return iterate(0);
}
}
Then use like so:
//Use in test
const FilesInDirectory = require('./utilities/getfilesindirectory');
const StepsCollection = new FilesInDirectory('./test-steps');
const StepsGenerator = StepsCollection.nextFileGenerator();
//Assuming we're in an async function
await StepsGenerator.next().value.FUNCTION_REQUIRED_FROM_FILE(someArg);

Resources