diff --git a/doc/api/modules.markdown b/doc/api/modules.markdown index 57cd78b36b6738..8212bd07c67627 100644 --- a/doc/api/modules.markdown +++ b/doc/api/modules.markdown @@ -57,6 +57,169 @@ The `square` module is defined in `square.js`: 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 you can 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 Node.js's `require()` function were designed to be general +enough to support a number of sane 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//` hold the contents of a +specific version of a package. + +Packages can depend on one another. In order to install package `foo`, you +may have to install a specific version of package `bar`. The `bar` package +may itself have dependencies, and in some cases, these dependencies may even +collide or form cycles. + +Since Node.js looks up the `realpath` of any modules it loads (that is, +resolves symlinks), and then looks for their dependencies in the +`node_modules` folders as described above, this situation is very simple to +resolve with the following architecture: + +* `/usr/lib/node/foo/1.2.3/` - Contents of the `foo` package, version 1.2.3. +* `/usr/lib/node/bar/4.3.2/` - Contents of the `bar` package that `foo` + depends 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 + that `bar` depends 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//`. 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. + +## All Together... + + + +To get the exact filename that will be loaded when `require()` is called, use +the `require.resolve()` function. + +Putting together all of the above, here is the high-level algorithm +in pseudocode of what require.resolve does: + + require(X) from module at path Y + 1. If X is a core module, + a. return the core module + b. STOP + 2. If X begins with './' or '/' or '../' + a. LOAD_AS_FILE(Y + X) + b. LOAD_AS_DIRECTORY(Y + X) + 3. LOAD_NODE_MODULES(X, dirname(Y)) + 4. THROW "not found" + + LOAD_AS_FILE(X) + 1. If X is a file, load X as JavaScript text. STOP + 2. If X.js is a file, load X.js as JavaScript text. STOP + 3. If X.json is a file, parse X.json to a JavaScript Object. STOP + 4. If X.node is a file, load X.node as binary addon. STOP + + LOAD_AS_DIRECTORY(X) + 1. If X/package.json is a file, + a. Parse X/package.json, and look for "main" field. + b. let M = X + (json main field) + c. LOAD_AS_FILE(M) + 2. If X/index.js is a file, load X/index.js as JavaScript text. STOP + 3. If X/index.json is a file, parse X/index.json to a JavaScript object. STOP + 4. If X/index.node is a file, load X/index.node as binary addon. STOP + + LOAD_NODE_MODULES(X, START) + 1. let DIRS=NODE_MODULES_PATHS(START) + 2. for each DIR in DIRS: + a. LOAD_AS_FILE(DIR/X) + b. LOAD_AS_DIRECTORY(DIR/X) + + NODE_MODULES_PATHS(START) + 1. let PARTS = path split(START) + 2. let I = count of PARTS - 1 + 3. let DIRS = [] + 4. while I >= 0, + a. if PARTS[I] = "node_modules" CONTINUE + c. DIR = path join(PARTS[0 .. I] + "node_modules") + b. DIRS = DIRS + DIR + c. let I = I - 1 + 5. return DIRS + +## Caching + + + +Modules are cached after the first time they are loaded. This means +(among other things) that every call to `require('foo')` will get +exactly the same object returned, if it would resolve to the same file. + +Multiple calls to `require('foo')` may not cause the module code to be +executed multiple times. This is an important feature. With it, +"partially done" objects can be returned, thus allowing transitive +dependencies to be loaded even when they would cause cycles. + +If you want to have a module execute code multiple times, then export a +function, and call that function. + +### Module Caching Caveats + + + +Modules are cached based on their resolved filename. Since modules may +resolve to a different filename based on the location of the calling +module (loading from `node_modules` folders), it is not a *guarantee* +that `require('foo')` will always return the exact same object, if it +would resolve to different files. + +## Core Modules + + + +Node.js has several modules compiled into the binary. These modules are +described in greater detail elsewhere in this documentation. + +The core modules are defined within Node.js's source and are located in the +`lib/` folder. + +Core modules are always preferentially loaded if their identifier is +passed to `require()`. For instance, `require('http')` will always +return the built in HTTP module, even if there is a file by that name. + ## Cycles @@ -113,20 +276,6 @@ The output of this program would thus be: If you have cyclic module dependencies in your program, make sure to plan accordingly. -## Core Modules - - - -Node.js has several modules compiled into the binary. These modules are -described in greater detail elsewhere in this documentation. - -The core modules are defined within Node.js's source and are located in the -`lib/` folder. - -Core modules are always preferentially loaded if their identifier is -passed to `require()`. For instance, `require('http')` will always -return the built in HTTP module, even if there is a file by that name. - ## File Modules @@ -153,36 +302,6 @@ either be a core module or is loaded from a `node_modules` folder. If the given path does not exist, `require()` will throw an Error with its `code` property set to `'MODULE_NOT_FOUND'`. -## Loading from `node_modules` Folders - - - -If the module identifier passed to `require()` is not a native module, -and does not begin with `'/'`, `'../'`, or `'./'`, then Node.js starts at the -parent directory of the current module, and adds `/node_modules`, and -attempts to load the module from that location. - -If it is not found there, then it moves to the parent directory, and so -on, until the root of the file system is reached. - -For example, if the file at `'/home/ry/projects/foo.js'` called -`require('bar.js')`, then Node.js would look in the following locations, in -this order: - -* `/home/ry/projects/node_modules/bar.js` -* `/home/ry/node_modules/bar.js` -* `/home/node_modules/bar.js` -* `/node_modules/bar.js` - -This allows programs to localize their dependencies, so that they do not -clash. - -You can require specific files or sub modules distributed with a module by -including a path suffix after the module name. For instance -`require('example-module/path/to/file')` would resolve `path/to/file` -relative to where `example-module` is located. The suffixed path follows the -same module resolution semantics. - ## Folders as Modules @@ -213,31 +332,69 @@ example, then `require('./some-library')` would attempt to load: * `./some-library/index.js` * `./some-library/index.node` -## Caching +## Loading from `node_modules` Folders -Modules are cached after the first time they are loaded. This means -(among other things) that every call to `require('foo')` will get -exactly the same object returned, if it would resolve to the same file. +If the module identifier passed to `require()` is not a native module, +and does not begin with `'/'`, `'../'`, or `'./'`, then Node.js starts at the +parent directory of the current module, and adds `/node_modules`, and +attempts to load the module from that location. -Multiple calls to `require('foo')` may not cause the module code to be -executed multiple times. This is an important feature. With it, -"partially done" objects can be returned, thus allowing transitive -dependencies to be loaded even when they would cause cycles. +If it is not found there, then it moves to the parent directory, and so +on, until the root of the file system is reached. -If you want to have a module execute code multiple times, then export a -function, and call that function. +For example, if the file at `'/home/ry/projects/foo.js'` called +`require('bar.js')`, then Node.js would look in the following locations, in +this order: -### Module Caching Caveats +* `/home/ry/projects/node_modules/bar.js` +* `/home/ry/node_modules/bar.js` +* `/home/node_modules/bar.js` +* `/node_modules/bar.js` - +This allows programs to localize their dependencies, so that they do not +clash. -Modules are cached based on their resolved filename. Since modules may -resolve to a different filename based on the location of the calling -module (loading from `node_modules` folders), it is not a *guarantee* -that `require('foo')` will always return the exact same object, if it -would resolve to different files. +You can require specific files or sub modules distributed with a module by +including a path suffix after the module name. For instance +`require('example-module/path/to/file')` would resolve `path/to/file` +relative to where `example-module` is located. The suffixed path follows the +same module resolution semantics. + +## Loading from the global folders + + + +If the `NODE_PATH` environment variable is set to a colon-delimited list +of absolute paths, then Node.js will search those paths for modules if they +are not found elsewhere. (Note: On Windows, `NODE_PATH` is delimited by +semicolons instead of colons.) + +`NODE_PATH` was originally created to support loading modules from +varying paths before the current +[module resolution](https://nodejs.org/api/modules.html#modules_all_together) +algorithm was frozen. + +`NODE_PATH` is still supported, but is less necessary now that the Node.js +ecosystem has settled on a convention for locating dependent modules. +Sometimes deployments that rely on `NODE_PATH` show surprising behavior +when people are unaware that `NODE_PATH` must be set. Sometimes a +module's dependencies change, causing a different version (or even a +different module) to be loaded as the `NODE_PATH` is searched. + +Additionally, Node.js will search in the following locations: + +* 1: `$HOME/.node_modules` +* 2: `$HOME/.node_libraries` +* 3: `$PREFIX/lib/node` + +Where `$HOME` is the user's home directory, and `$PREFIX` is Node.js's +configured `node_prefix`. + +These are mostly for historic reasons. **You are highly encouraged +to place your dependencies locally in `node_modules` folders.** They +will be loaded faster, and more reliably. ## The `module` Object @@ -251,6 +408,12 @@ representing the current module. For convenience, `module.exports` is also accessible via the `exports` module-global. `module` isn't actually a global but rather local to each module. +### module.children + +* {Array} + +The module objects required by this one. + ### module.exports * {Object} @@ -318,19 +481,11 @@ To illustrate the behavior, imagine this hypothetical implementation of As a guideline, if the relationship between `exports` and `module.exports` seems like magic to you, ignore `exports` and only use `module.exports`. -### module.require(id) - -* `id` {String} -* Return: {Object} `module.exports` from the resolved module - -The `module.require` method provides a way to load a module as if -`require()` was called from the original module. +### module.filename -Note that in order to do this, you must get a reference to the `module` -object. Since `require()` returns the `module.exports`, and the `module` is -typically *only* available within a specific module's code, it must be -explicitly exported in order to be used. +* {String} +The fully resolved filename to the module. ### module.id @@ -339,14 +494,6 @@ explicitly exported in order to be used. The identifier for the module. Typically this is the fully resolved filename. - -### module.filename - -* {String} - -The fully resolved filename to the module. - - ### module.loaded * {Boolean} @@ -354,174 +501,21 @@ The fully resolved filename to the module. Whether or not the module is done loading, or is in the process of loading. - ### module.parent * {Module Object} The module that first required this one. -### module.children - -* {Array} - -The module objects required by this one. - - - -## All Together... - - - -To get the exact filename that will be loaded when `require()` is called, use -the `require.resolve()` function. - -Putting together all of the above, here is the high-level algorithm -in pseudocode of what require.resolve does: - - require(X) from module at path Y - 1. If X is a core module, - a. return the core module - b. STOP - 2. If X begins with './' or '/' or '../' - a. LOAD_AS_FILE(Y + X) - b. LOAD_AS_DIRECTORY(Y + X) - 3. LOAD_NODE_MODULES(X, dirname(Y)) - 4. THROW "not found" - - LOAD_AS_FILE(X) - 1. If X is a file, load X as JavaScript text. STOP - 2. If X.js is a file, load X.js as JavaScript text. STOP - 3. If X.json is a file, parse X.json to a JavaScript Object. STOP - 4. If X.node is a file, load X.node as binary addon. STOP - - LOAD_AS_DIRECTORY(X) - 1. If X/package.json is a file, - a. Parse X/package.json, and look for "main" field. - b. let M = X + (json main field) - c. LOAD_AS_FILE(M) - 2. If X/index.js is a file, load X/index.js as JavaScript text. STOP - 3. If X/index.json is a file, parse X/index.json to a JavaScript object. STOP - 4. If X/index.node is a file, load X/index.node as binary addon. STOP - - LOAD_NODE_MODULES(X, START) - 1. let DIRS=NODE_MODULES_PATHS(START) - 2. for each DIR in DIRS: - a. LOAD_AS_FILE(DIR/X) - b. LOAD_AS_DIRECTORY(DIR/X) - - NODE_MODULES_PATHS(START) - 1. let PARTS = path split(START) - 2. let I = count of PARTS - 1 - 3. let DIRS = [] - 4. while I >= 0, - a. if PARTS[I] = "node_modules" CONTINUE - c. DIR = path join(PARTS[0 .. I] + "node_modules") - b. DIRS = DIRS + DIR - c. let I = I - 1 - 5. return DIRS - -## Loading from the global folders - - - -If the `NODE_PATH` environment variable is set to a colon-delimited list -of absolute paths, then Node.js will search those paths for modules if they -are not found elsewhere. (Note: On Windows, `NODE_PATH` is delimited by -semicolons instead of colons.) - -`NODE_PATH` was originally created to support loading modules from -varying paths before the current -[module resolution](https://nodejs.org/api/modules.html#modules_all_together) -algorithm was frozen. - -`NODE_PATH` is still supported, but is less necessary now that the Node.js -ecosystem has settled on a convention for locating dependent modules. -Sometimes deployments that rely on `NODE_PATH` show surprising behavior -when people are unaware that `NODE_PATH` must be set. Sometimes a -module's dependencies change, causing a different version (or even a -different module) to be loaded as the `NODE_PATH` is searched. - -Additionally, Node.js will search in the following locations: - -* 1: `$HOME/.node_modules` -* 2: `$HOME/.node_libraries` -* 3: `$PREFIX/lib/node` - -Where `$HOME` is the user's home directory, and `$PREFIX` is Node.js's -configured `node_prefix`. - -These are mostly for historic reasons. **You are highly encouraged -to place your dependencies locally in `node_modules` folders.** They -will be loaded faster, and more reliably. - -## Accessing the main module - - - -When a file is run directly from Node.js, `require.main` is set to its -`module`. That means that you can 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 Node.js's `require()` function were designed to be general -enough to support a number of sane 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//` hold the contents of a -specific version of a package. - -Packages can depend on one another. In order to install package `foo`, you -may have to install a specific version of package `bar`. The `bar` package -may itself have dependencies, and in some cases, these dependencies may even -collide or form cycles. - -Since Node.js looks up the `realpath` of any modules it loads (that is, -resolves symlinks), and then looks for their dependencies in the -`node_modules` folders as described above, this situation is very simple to -resolve with the following architecture: - -* `/usr/lib/node/foo/1.2.3/` - Contents of the `foo` package, version 1.2.3. -* `/usr/lib/node/bar/4.3.2/` - Contents of the `bar` package that `foo` - depends 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 - that `bar` depends 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. +### module.require(id) -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`. +* `id` {String} +* Return: {Object} `module.exports` from the resolved module -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//`. Then Node.js will not bother -looking for missing dependencies in `/usr/node_modules` or `/node_modules`. +The `module.require` method provides a way to load a module as if +`require()` was called from the original module. -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. +Note that in order to do this, you must get a reference to the `module` +object. Since `require()` returns the `module.exports`, and the `module` is +typically *only* available within a specific module's code, it must be +explicitly exported in order to be used.