How does require work? - node.js

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

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

Nodejs require module from external folder

I'm developing microservice architecture on nodejs.
I moved 'core' functionality to separate git repository, and each 'service' add that core as npm dependency.
In service I use core as
require('core/module1');
In that case nodejs takes 'core' from node_modules, it's ok for production but for development I want to take 'core' from the external folder not from node_modules.
My main idea - do changes in 'core' and immidiately get the result in 'service'.
I cannot use NODE_PATH for specify external 'core' folder, because I've used it now.
I found solution to use 'app-module-path' module for adding additional directories to the Node.js module search path.
if(isDevelopment()){
require('app-module-path').addPath('path_to_core_folder');
}
It's working solution, but maybe you can suggest some more clear way?
My folders structure
- core
module1
- service1
-index.js
-node_modules
-core
Thanks.
Either one works. If you require('modulename') and it's present in your node_modules folder, it will be loaded from there. If you want it to load from another folder or from your main folder, you need to do require('./modulename") which will look for it in the current folder. Alternatively you can do require('./my_modules/modulename') which will work for a subfolder.
i would look at the mockrequire module, it allows you to redirect the directory your modules are loaded from
npm link is the answer to your problem. You can run the below command in the root directory of 'service1' (where your package.json is present)
npm link [../relative-path-to/library]
Refer to https://docs.npmjs.com/cli/v7/commands/npm-link for more details about npm link.

how to define a file as a module in 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.

Get the node.js install path from code

I'm trying to write a debugging framework for node.js and am having a hard time figuring out how to get the full path to a core module file like fs.js.
I've heard it's in the /lib folder of the node installation, but I'd need to get this from the code in a consistent way for a variety of install situations (including windows).
I've tried taking a look at the process and process.env values for something like a node install path but can't see anything that immediately pops out at me.
To find where the installed node executable is located you can look at the process.execPath which gives the absolute path to Node executable.
To find where a certain module is located you can use require.resolve(module);
However I think the global modules are not directly accessible from the filesystem as other regular modules since they seem to be cached somewhere within the executable.

Resources