Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'doc/api/modules.md')
-rw-r--r--doc/api/modules.md563
1 files changed, 563 insertions, 0 deletions
diff --git a/doc/api/modules.md b/doc/api/modules.md
new file mode 100644
index 00000000000..20c8b175cd9
--- /dev/null
+++ b/doc/api/modules.md
@@ -0,0 +1,563 @@
+# Modules
+
+ Stability: 3 - Locked
+
+<!--name=module-->
+
+Node.js has a simple module loading system. In Node.js, files and modules are
+in one-to-one correspondence. As an example, `foo.js` loads the module
+`circle.js` in the same directory.
+
+The contents of `foo.js`:
+
+```js
+const circle = require('./circle.js');
+console.log( `The area of a circle of radius 4 is ${circle.area(4)}`);
+```
+
+The contents of `circle.js`:
+
+```js
+const PI = Math.PI;
+
+exports.area = (r) => PI * r * r;
+
+exports.circumference = (r) => 2 * PI * r;
+
+```
+
+The module `circle.js` has exported the functions `area()` and
+`circumference()`. To add functions and objects to the root of your module,
+you can add them to the special `exports` object.
+
+Variables local to the module will be private, as though the module was wrapped
+in a function. In this example the variable `PI` is private to `circle.js`.
+
+If you want the root of your module's export to be a function (such as a
+constructor) or if you want to export a complete object in one assignment
+instead of building it one property at a time, assign it to `module.exports`
+instead of `exports`.
+
+Below, `bar.js` makes use of the `square` module, which exports a constructor:
+
+```js
+const square = require('./square.js');
+var mySquare = square(2);
+console.log(`The area of my square is ${mySquare.area()}`);
+```
+
+The `square` module is defined in `square.js`:
+
+```js
+// assigning to exports will not modify module, must use module.exports
+module.exports = (width) => {
+ return {
+ area: () => width * width
+ };
+}
+```
+
+The module system is implemented in the `require("module")` module.
+
+## Accessing the main module
+
+<!-- type=misc -->
+
+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
+
+```js
+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
+
+<!-- type=misc -->
+
+The semantics of Node.js's `require()` function were designed to be general
+enough to support a number of 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`, 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 [here](#modules_loading_from_node_modules_folders), 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/<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.
+
+## All Together...
+
+<!-- type=misc -->
+
+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
+
+<!--type=misc-->
+
+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
+
+<!--type=misc-->
+
+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.
+
+Additionally, on case-insensitive file systems or operating systems, different
+resolved filenames can point to the same file, but the cache will still treat
+them as different modules and will reload the file multiple times. For example,
+`require('./foo')` and `require('./FOO')` return two different objects,
+irrespective of whether or not `./foo` and `./FOO` are the same file.
+
+## Core Modules
+
+<!--type=misc-->
+
+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
+
+<!--type=misc-->
+
+When there are circular `require()` calls, a module might not have finished
+executing when it is returned.
+
+Consider this situation:
+
+`a.js`:
+
+```
+console.log('a starting');
+exports.done = false;
+const b = require('./b.js');
+console.log('in a, b.done = %j', b.done);
+exports.done = true;
+console.log('a done');
+```
+
+`b.js`:
+
+```
+console.log('b starting');
+exports.done = false;
+const a = require('./a.js');
+console.log('in b, a.done = %j', a.done);
+exports.done = true;
+console.log('b done');
+```
+
+`main.js`:
+
+```
+console.log('main starting');
+const a = require('./a.js');
+const b = require('./b.js');
+console.log('in main, a.done=%j, b.done=%j', a.done, b.done);
+```
+
+When `main.js` loads `a.js`, then `a.js` in turn loads `b.js`. At that
+point, `b.js` tries to load `a.js`. In order to prevent an infinite
+loop, an **unfinished copy** of the `a.js` exports object is returned to the
+`b.js` module. `b.js` then finishes loading, and its `exports` object is
+provided to the `a.js` module.
+
+By the time `main.js` has loaded both modules, they're both finished.
+The output of this program would thus be:
+
+```
+$ node main.js
+main starting
+a starting
+b starting
+in b, a.done = false
+b done
+in a, b.done = true
+a done
+in main, a.done=true, b.done=true
+```
+
+If you have cyclic module dependencies in your program, make sure to
+plan accordingly.
+
+## File Modules
+
+<!--type=misc-->
+
+If the exact filename is not found, then Node.js will attempt to load the
+required filename with the added extensions: `.js`, `.json`, and finally
+`.node`.
+
+`.js` files are interpreted as JavaScript text files, and `.json` files are
+parsed as JSON text files. `.node` files are interpreted as compiled addon
+modules loaded with `dlopen`.
+
+A required module prefixed with `'/'` is an absolute path to the file. For
+example, `require('/home/marco/foo.js')` will load the file at
+`/home/marco/foo.js`.
+
+A required module prefixed with `'./'` is relative to the file calling
+`require()`. That is, `circle.js` must be in the same directory as `foo.js` for
+`require('./circle')` to find it.
+
+Without a leading '/', './', or '../' to indicate a file, the module must
+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'`.
+
+## Folders as Modules
+
+<!--type=misc-->
+
+It is convenient to organize programs and libraries into self-contained
+directories, and then provide a single entry point to that library.
+There are three ways in which a folder may be passed to `require()` as
+an argument.
+
+The first is to create a `package.json` file in the root of the folder,
+which specifies a `main` module. An example package.json file might
+look like this:
+
+```
+{ "name" : "some-library",
+ "main" : "./lib/some-library.js" }
+```
+
+If this was in a folder at `./some-library`, then
+`require('./some-library')` would attempt to load
+`./some-library/lib/some-library.js`.
+
+This is the extent of Node.js's awareness of package.json files.
+
+Note: If the file specified by the `"main"` entry of `package.json` is missing
+and can not be resolved, Node.js will report the entire module as missing with
+the default error:
+
+```
+Error: Cannot find module 'some-library'
+```
+
+If there is no package.json file present in the directory, then Node.js
+will attempt to load an `index.js` or `index.node` file out of that
+directory. For example, if there was no package.json file in the above
+example, then `require('./some-library')` would attempt to load:
+
+* `./some-library/index.js`
+* `./some-library/index.node`
+
+## Loading from `node_modules` Folders
+
+<!--type=misc-->
+
+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. Node will not append
+`node_modules` to a path already ending in `node_modules`.
+
+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.
+
+## Loading from the global folders
+
+<!-- type=misc -->
+
+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][] 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
+
+<!-- type=var -->
+<!-- name=module -->
+
+* {Object}
+
+In each module, the `module` free variable is a reference to the object
+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}
+
+The `module.exports` object is created by the Module system. Sometimes this is
+not acceptable; many want their module to be an instance of some class. To do
+this, assign the desired export object to `module.exports`. Note that assigning
+the desired object to `exports` will simply rebind the local `exports` variable,
+which is probably not what you want to do.
+
+For example suppose we were making a module called `a.js`
+
+```js
+const EventEmitter = require('events');
+
+module.exports = new EventEmitter();
+
+// Do some work, and after some time emit
+// the 'ready' event from the module itself.
+setTimeout(() => {
+ module.exports.emit('ready');
+}, 1000);
+```
+
+Then in another file we could do
+
+```js
+const a = require('./a');
+a.on('ready', () => {
+ console.log('module a is ready');
+});
+```
+
+
+Note that assignment to `module.exports` must be done immediately. It cannot be
+done in any callbacks. This does not work:
+
+x.js:
+
+```js
+setTimeout(() => {
+ module.exports = { a: 'hello' };
+}, 0);
+```
+
+y.js:
+
+```js
+const x = require('./x');
+console.log(x.a);
+```
+
+#### exports alias
+
+The `exports` variable that is available within a module starts as a reference
+to `module.exports`. As with any variable, if you assign a new value to it, it
+is no longer bound to the previous value.
+
+To illustrate the behavior, imagine this hypothetical implementation of
+`require()`:
+
+```js
+function require(...) {
+ // ...
+ ((module, exports) => {
+ // Your module code here
+ exports = some_func; // re-assigns exports, exports is no longer
+ // a shortcut, and nothing is exported.
+ module.exports = some_func; // makes your module export 0
+ })(module, module.exports);
+ return module;
+}
+```
+
+As a guideline, if the relationship between `exports` and `module.exports`
+seems like magic to you, ignore `exports` and only use `module.exports`.
+
+### module.filename
+
+* {String}
+
+The fully resolved filename to the module.
+
+### module.id
+
+* {String}
+
+The identifier for the module. Typically this is the fully resolved
+filename.
+
+### module.loaded
+
+* {Boolean}
+
+Whether or not the module is done loading, or is in the process of
+loading.
+
+### module.parent
+
+* {Object} Module object
+
+The module that first required this one.
+
+### 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.
+
+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.
+
+[`Error`]: errors.html#errors_class_error
+[module resolution]: #modules_all_together