What is exports.install in node js? - node.js

Hi I found a framework where they use a lot this pattern.
exports.install = function(){
//code
}
but usually you see this pattern in nodejs
module.exports = {
//code
}
Is this the same thing or is this something else ?

exports is the object corresponding to module.exports before you do anything to it. I think it's due to some legacy code, but basically folks use module.exports if they want to replace the whole object with their own object or a function, while they use exports if they just want to hang functions off the module. It's a little confusing at first, but essentially exports.install just means that calling code would do something like:
const mod = require('that-module');
mod.install(params, callback); // call that function
The framework you're looking at is probably using it as part of a bootstrapping process, afaik it doesn't have significance to the node engine itself.

Yes, it is the same thing. You can use one of 2 ways to setup your code.
The different thing is memory. They point to same memory. You can think exports like a variable and you can not use this way to export your module:
Given this module:
// test.js
exports = {
// you can not use this way to export module.
// because at this time, `exports` points to another memory region
// and it did not lie on same memory with `module.exports`
sayHello: function() {
console.log("Hello !");
}
}
The following code will get the error: TypeError: test.sayHello is not a function
// app.js
var test = require("./test");
test.sayHello();
// You will get TypeError: test.sayHello is not a function
The correct way you must use module.exports to export your module:
// test.js
module.exports = {
// you can not use this way to export module.
sayHello: function() {
console.log("Hello !");
}
}
// app.js
var test = require("./test");
test.sayHello();
// Console prints: Hello !
So, it just is style of developer.

Related

Best way to invoke code inside a module in nodejs

From a performance perspective, is there any difference between invoking code by wrapping it in a function and then exporting it:
function doSomething () {
// doing something here
}
module.exports = doSomething();
And just requiring it without any exports? like this:
myModule.js
// Code doing something
file that requires the module:
var doSomething = require('./myModule');
And if the purpose of the code inside the module is to run just once, do I need to store it in a variable?
If you don't need the return value of that function, then you don't have to store it in a variable.
The difference with:
function doSomething () {
// doing something here
}
module.exports = doSomething();
and using:
var x = require('module');
var y = require('module');
vs.
function doSomething () {
// doing something here
}
module.exports = doSomething;
and using:
var x = require('module')();
var y = require('module')();
is that in the first case, the function will be run only once, while in the second case the function will be run twice.
The difference is that if you just include it without module.exports, then the code will execute immediately but be private to the module. You can only access the data if you export it somehow, with module.exports. It can be either a function or a Javascript Object. Essentially, you can view everything within the module as being completely hidden from everything else in your application.
The only shortcut that I know of is for JSON files. If you look here: Module.exports vs plain json for config files, you can see that you can require('file.json') and it will replace the contents of the json file with a Javascript object that you can then use in your application.

Understanding ExpressJS application start-up

I am struggling with how application start-up works in Express. I am going to explain my use-case:
I have a configuration-Manager module which is used by all other application modules to load required configuration. I am setting configuration in app.listen:
app.listen(9000, function () {
try
{
config_manager.setSiteConfig();
console.log('settings..!!!')
}
catch(err)
{
console.log(err.stack);
}
});
In another module of the same application I call the Configuration-Manager function to load config, but it returns empty. Code is something like this:
var config_manager = require('configuration-manager');
console.log(config_manager.loadConfig()); // returns empty object {}
I am running the application using node app.js. The empty object gets printed first then ('settings..!!!'). Does Express compile the script before calling app.listen()? How do I make sure that my configuration is set before compilation/loading other files?
Express indeed first processes all statements in a file, basically anything that isn't in a function on startup.
In your case var config_manager = require('configuration-manager');
console.log(config_manager.loadConfig()); // returns empty object {} is executed before your app.listen because you are requering the config before the app.listen.
You're best off processing your configuration right after the first time it is required (if app.js is your main file, this means the first time it comes across a require statement pointing to configuration-manager in any file).
This should make your code work:
var config_manager = require('configuration-manager');
try {
config_manager.setSiteConfig();
} catch(err) {
console.log(err.stack);
}
console.log(config_manager.loadConfig()); // returns empty object {}
and then
app.listen(9000, function () {
console.log('settings..!!!', config_manager.loadConfig()) // Should correctly print your config
});
If this doesn't work the problem does not lay in the order of execution.

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

NodeJS - Requiring module returns empty array

Writing the simplest module we could, we write into hello.js:
var hello = function(){
console.log('hello');
};
exports = hello; \\ Doesn't work on Amazon EC2 Ubuntu Instance nor Windows Powershell
I run Node and require the module
var hello = require('./hello');
hello;
and an empty array {} gets returned when I'm supposed to get [Function].
I tried replacing exports with module.exports, but this doesn't work on my Windows Powershell. It does work on my Amazon EC2 Ubuntu Instance, so why doesn't exports work? Has the API changed? And what could possibly be happening with Powershell that neither of these work?
I know Windows isn't the most desirable development environment, but I can't get my head around such a simple mishap.
EDIT
exporting with ES6 is a little nicer
export const hello = function(){
console.log('hello');
};
importing will look like
import {hello} from './file';
Original answer
You'll want to use module.exports
var hello = function(){
console.log('hello');
};
module.exports = hello;
If just exporting one thing, I'll usually do it all in one line
var hello = module.exports = function() {
console.log('hello');
};
Extras
If you use a named function, in the event an error occurs in your code, your stack trace will look a lot nicer. Here's the way I would write it
// use a named function ↓
var hello = module.exports = function hello() {
console.log("hello");
};
Now instead of showing anonymous for the function name in the stack trace, it will show you hello. This makes finding bugs so much easier.
I use this pattern everywhere so that I can debug code easily. Here's another example
// event listeners ↓
mystream.on("end", function onEnd() {
console.log("mystream ended");
};
// callbacks ↓
Pokemon.where({name: "Metapod"}, function pokemonWhere(err, result) {
// do stuff
});
If you want to export multiple things, you can use exports directly, but you must provide a key
// lib/foobar.js
exports.foo = function foo() {
console.log("hello foo!");
};
exports.bar = function bar() {
console.log("hello bar!");
};
Now when you use that file
var foobar = require("./lib/foobar");
foobar.foo(); // hello foo!
foobar.bar(); // hello bar!
As a final bonus, I'll show you how you can rewrite that foobar.js by exporting a single object but still getting the same behavior
// lib/foobar.js
module.exports = {
foo: function foo() {
console.log("hello foo!");
},
bar: function bar() {
console.log("hello bar!");
}
};
// works the same as before!
This allows you to write modules in whichever way is best suited for that particular module. Yay!
The reason exports is not working is because of the reference conflict. The top variable in each file is module which has a property module.exports. When the module is loaded new variable is created in the background. Something like this happens:
var exports = module.exports;
Obviously exports is a reference to module.exports, but doing
exports = function(){};
forces exports variable to point at function object - it does not change module.exports. It's like doing:
var TEST = { foo: 1 };
var foo = TEST.foo;
foo = "bar";
console.log(TEST.foo);
// 1
Common practice is to do:
module.exports = exports = function() { ... };
I have no idea why it doesn't work under Windows Powershell. To be honest I'm not even sure what that is. :) Can't you just use native command prompt?

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 ..

Resources