- Assertion testing
- Async hooks
- Buffer
- C++ addons
- C/C++ addons with Node-API
- C++ embedder API
- Child processes
- Cluster
- Command-line options
- Console
- Crypto
- Debugger
- Deprecated APIs
- Diagnostics Channel
- DNS
- Domain
- Errors
- Events
- File system
- Globals
- HTTP
- HTTP/2
- HTTPS
- Inspector
- Internationalization
- Modules: CommonJS modules
- Modules: ECMAScript modules
- Modules:
moduleAPI - Modules: Packages
- Net
- OS
- Path
- Performance hooks
- Policies
- Process
- Punycode
- Query strings
- Readline
- REPL
- Report
- Stream
- String decoder
- Timers
- TLS/SSL
- Trace events
- TTY
- UDP/datagram
- URL
- Utilities
- V8
- VM
- WASI
- Worker threads
- Zlib
Node.js v14.17.4 documentation
Table of contents
- Modules: CommonJS modules
- Accessing the main module
- Addenda: Package manager tips
- Addenda: The
.mjsextension - All together...
- Caching
- Core modules
- Cycles
- File modules
- Folders as modules
- Loading from
node_modulesfolders - Loading from the global folders
- The module wrapper
- The module scope
- The
moduleobject - The
Moduleobject - Source map v3 support
Modules: CommonJS modules#
In the Node.js module system, each file is treated as a separate module. For
example, consider a file named foo.js:
const circle = require('./circle.js');
console.log(`The area of a circle of radius 4 is ${circle.area(4)}`);
On the first line, foo.js loads the module circle.js that is in the same
directory as foo.js.
Here are the contents of circle.js:
const { PI } = Math;
exports.area = (r) => PI * r ** 2;
exports.circumference = (r) => 2 * PI * r;
The module circle.js has exported the functions area() and
circumference(). Functions and objects are added to the root of a module
by specifying additional properties on the special exports object.
Variables local to the module will be private, because the module is wrapped
in a function by Node.js (see module wrapper).
In this example, the variable PI is private to circle.js.
The module.exports property can be assigned a new value (such as a function
or object).
Below, bar.js makes use of the square module, which exports a Square class:
const Square = require('./square.js');
const mySquare = new Square(2);
console.log(`The area of mySquare is ${mySquare.area()}`);
The square module is defined in square.js:
// Assigning to exports will not modify module, must use module.exports
module.exports = class Square {
constructor(width) {
this.width = width;
}
area() {
return this.width ** 2;
}
};
The module system is implemented in the require('module') module.
Accessing the main module#
When a file is run directly from Node.js, require.main is set to its
module. That means that it is possible to determine whether a file has been
run directly by testing require.main === module.
For a file foo.js, this will be true if run via node foo.js, but
false if run by require('./foo').
Because module provides a filename property (normally equivalent to
__filename), the entry point of the current application can be obtained
by checking require.main.filename.
Addenda: Package manager tips#
The semantics of the Node.js require() function were designed to be general
enough to support reasonable directory structures. Package manager programs
such as dpkg, rpm, and npm will hopefully find it possible to build
native packages from Node.js modules without modification.
Below we give a suggested directory structure that could work:
Let's say that we wanted to have the folder at
/usr/lib/node/<some-package>/<some-version> hold the contents of a
specific version of a package.
Packages can depend on one another. In order to install package foo, it
may be necessary to install a specific version of package bar. The bar
package may itself have dependencies, and in some cases, these may even collide
or form cyclic dependencies.
Because Node.js looks up the realpath of any modules it loads (that is, it
resolves symlinks) and then looks for their dependencies in node_modules folders,
this situation can be resolved with the following architecture:
/usr/lib/node/foo/1.2.3/: Contents of thefoopackage, version 1.2.3./usr/lib/node/bar/4.3.2/: Contents of thebarpackage thatfoodepends on./usr/lib/node/foo/1.2.3/node_modules/bar: Symbolic link to/usr/lib/node/bar/4.3.2/./usr/lib/node/bar/4.3.2/node_modules/*: Symbolic links to the packages thatbardepends on.
Thus, even if a cycle is encountered, or if there are dependency conflicts, every module will be able to get a version of its dependency that it can use.
When the code in the foo package does require('bar'), it will get the
version that is symlinked into /usr/lib/node/foo/1.2.3/node_modules/bar.
Then, when the code in the bar package calls require('quux'), it'll get
the version that is symlinked into
/usr/lib/node/bar/4.3.2/node_modules/quux.
Furthermore, to make the module lookup process even more optimal, rather
than putting packages directly in /usr/lib/node, we could put them in
/usr/lib/node_modules/<name>/<version>. Then Node.js will not bother
looking for missing dependencies in /usr/node_modules or /node_modules.
In order to make modules available to the Node.js REPL, it might be useful to
also add the /usr/lib/node_modules folder to the $NODE_PATH environment
variable. Since the module lookups using node_modules folders are all
relative, and based on the real path of the files making the calls to
require(), the packages themselves can be anywhere.
Addenda: The .mjs extension#
It is not possible to require() files that have the .mjs extension.
Attempting to do so will throw an error. The .mjs extension is
reserved for