how to define a file as a module in node.js - node.js

instead of requireing code relatively, ie starting with ./ or .., i'd like to define a module "globally". For example, take the following package structure:
/src
/index.js
/a.js
/b.js
/lib
/index.js
...
When in src/a.js or src/b.js, to require lib, I would have to do require('../lib') each time. This gets annoying when you start nesting more as you would have to manually resolve ../lib or ../../lib or ../../../lib.
I want to be able to do require('lib'). Can I do this? Or should I just use globals?

Using a non relative path to require your source files is not how node's require is intended to work! Don't try to work around this restriction by placing arbitrary code file in node_modules directory or workaround by changing the NODE_PATH environment variable.
If you want to use require without a path you should extract the required code as a node module and depend on this node module. This leads to better structured code, less complex modules, encapsulated functionality, better testability and easier code reuse.
You can include package dependencies from http or git so there is no requirement to publish node modules you use in npm. Take a look at npm dependencies for more detail.

use module.exports in the index.js file . and place it inside the node_modules folder

if relative path annoy you and you want to use lib always in your application, you can use global variable like this.
var lib = require('./lib');
global.lib = lib;
you can set lib to global variable in your entry point. after then you can access just lib.
but it's pollute global scope. so you have to use carefully.

placing your module in node_modules dont require you to include a path or relative path
EDIT:
if you place a file named package.json inside the module directory, Node will try to parse that file and look for and use the main attribute as a relative path for the entry point. For instance, if your
./myModuleDir/package.json
file looks something like the following, Node will try to load the file with the path
./myModuleDir/lib/myModule.js
:
{
"name" : "myModule",
"main" : "./lib/myModule.js"
}
If that folder does not contain a package definition file named package.json, the package entry point will assume the default value of index.js, and Node will look, in this case, for a file under the path ./myModuleDir/index.js.

Related

Why does require("the-module") from a file in another directory fail?

When I did node myfile.js I got an error that a module was not found. I checked module.paths like this:
$ node
> module.paths
The path where the module is installed showed up and I could require the module:
$ node
> require("the-module")
So I added console.log(module.paths) to myfile.js to see if module.paths was the same. It was not.
What is going on?
EDIT:
It was a bit more complicated.
The module.paths are different, but that does not seem to be the problem. The path where the-module is installed is in the list.
When I add require("the-module") in myfile.js it works as expected. However I do require("c:/path-to/other-file.js") and from there I do another require("the-module"). This require fails.
EDIT 2:
module.paths is other-file.js is different. Why? (And the path where the-module is installed is not in this list.)
You can see all the rules for how require() loads files when you don't specify a full path here.
When you specific only a filename, as in require("the-module"), node.js looks in the node_modules sub-directory below the directory that the current module you are calling require() from was loaded. It is done this way so that a module can have its own set of dependencies and can load them relative to it's own directory without regard from where it is in the file system.
So, if the module you are calling require() from was in c:\myprojects\team\module1 and from within a file in that directory, you call require("the-module"), then node.js will look in c:\myprojects\team\module1\node_modules to find the-module.js.
Similarly, any path that starts with ./ is relative to that same directory, but allows you to reference files in the same directory itself.
node.js does not dynamically add paths to a list of search paths. It sounds like you have an expectation that as you access various directories they are somehow automatically added to a search path. That's now how it works. The rules for where require() looks for relative paths are all spelled out here.
Also, keep in mind that there is not just one module variable across all of node.js. There's a different one in each file that you load in node.js so module.paths very well may be different in each one. In reality, most node.js developers never use module.paths in any way. If you just follow the rules for how relative paths work for require(), you will get what you expect and need.

How does require work?

I have 2 files in a folder called js. I am using webpack.
js/app.js and js/login.es6.
I'm trying to include the login from my app.js:
require('login.es6') fails
require('./login.es6') works.
Any idea why?
When you write require('login.es6') node will look for a module named login.es6 in your node_modules.
When you write require('./login.es6') node understands that ./login.es6 is a relative path and will load your js/login.es6.js file.
This is needed to distinguish between modules and local files. There may be a npm module called login.es6; this way you can reference both the module and your local file in your project.
The node.js docs on require are pretty nice and gives a good overview of how modules are prioritized when loaded.
The gist is, if you don't start the string with ./, require will first look for a core module, then recursively look in the node_modules directory/-ies. So it's normal to start require calls to local files with ./.

How to build node addon, so that it can be imported only by name, and not path

When I build a node add-on by creating a standard binding.gyp and running node-gyp build, the addon.node library is created in the subdirectory build/{Release|Debug}/. When I write tests or other javascript code to use this module, I have to give explicit path to the library location
For example,
var addon = require('./build/Release/addon')
However, I would like to do this by only specifying the module name and let node's module search for the library
var addon = require('addon')
How can that be achieved?
I believe the only way to do this is setting require() and having the module in the node_modules folder or having the module in a node_modules folder in one of the parent directories.
Node uses the require() method with no path defined as an indicator to look for the module in the node_modules directory. Unless its an native module.
Its detailed in the docs here.
There's a module for that if you're okay with another dependency.
https://www.npmjs.com/package/bindings
That will search all of the possible build output locations automatically, including debug and release directories.

require name instead of file path

I am looking at some code on github.
https://github.com/madhums/node-express-mongoose/blob/master/config/routes.js
On line 7 it says.
var home = require('home');
home.js is in another folder. I am wondering how this works, and how I can do this in my own code.
on
http://nodejs.org/api/modules.html#modules_folders_as_modules
it explains how to create a self-contained directory, but I can only find the package.json in the root folder. So how does this work?
It seems like a more clean way than having direct file references.
There are ways to refer to folders on the filesystem as packages in node, npm link for example, will pretend a folder is a module using symlinks.
The package you linked to is cheating a bit though, and I'd argue it's not clean at all when put like that. It's actually setting the NODE_PATH to include all controllers when the service is ran: https://github.com/madhums/node-express-mongoose/blob/master/package.json#L13
So all controllers files like home.js are autmatically available. The .js is always optional anyway.

How to provide module dependencies for required script in a sibling directory

I am running a node.js script (foo.js) that requires a helper script that is located in a sibling directory.
//foo.js:
var magic = require('../util/magic');
magic.js uses a npm module express. However, the main directory of the 'program' (holding package.json and node_modules) is the folder where foo.js is located.
/program
/node_modules
/express
..
/foo.js
/package.json
/util
/magic.js
When running the program, the statement require('express') in magic.js fails - the module cannot be found.
Is there a way to make node.js load the express module from the program/node_modules directory?
I would like to avoid any of the following:
move the node_modules directory to a common parent of util and program
add a node_modules directory to util
pass in a reference of the required modules to magic.js
Appreciate your help!
You could supply a relative path instead the module name, because this is how Node.js is going to check for the modules folder if you don't specify a path:
/util/node_modules
/node_modules
Since you know where the module already exists, just do this instead:
var express = require('../program/node_modules/express');
However, you should place any files related to the module within the module itself when developing modules. If you don't, they don't get packaged with the module either when it is published, and you have this inconvenience of not being able to access dependencies specified in the package file.

Resources