Nodejs Require execution process

Source: Internet
Author: User

Why add this must-read! Because the Webpack itself is based on the node environment,

There will be many path problems involved, we may write about paths! Webpack How to find these paths is very confused.

This article is I have finished the formal study react (five) after the new addition! I think it is necessary to let everyone know!

------------------------------------------------------------------------------------------------------

Nodejs require execution Process = = Webpack Path lookup process!

-----------------------------------------------------------------------------------------------------

The most common method of require
Require (' HTTP ') built-in modules

Require ('./server ') "./" represents the current path, followed by a relative path
Require (".. /lib/server "). /indicates the previous level of the directory, followed by a relative path


Server.js

[JavaScript]
var http = require (' http ');
function Start () {
Server = Http.createserver (function (req, res) {
Res.writeheader ($, {"Content-type": "Text/plain"});
Res.end ("Hello oschina\n");
})
Server.listen (8000);
Console.log ("httpd start @8000");
}
Exports.start = start;

Index.js

[JavaScript]
The path depends on your situation
var server = require ("./learnnode/server");
Server.start ();

The following describes require's just from the link: http://www.nodecn.org/modules.html#file_Modules

Module
Node uses the CommonJS module system.

Node has a simple module loading system. In Node, the file and module one by one correspond. For example, load the Circle.js module in the same directory in Foo.js.

Content of Foo.js:

var circle = require ('./circle.js ');
Console.log (' The area of a circle of radius 4 is '
+ Circle.area (4));
Content of Circle.js:

var PI = Math.PI;

Exports.area = function (r) {
return PI * R * r;
};

Exports.circumference = function (r) {
Return 2 * PI * r;
};
Module Circle.js exports the area () function and the circumference () function so that they can be accessed from outside the module. To export an object, add it to a special exports object on the line.

The local variables of the module are private. In this case, the variable PI is circle.js private.

Core modules
Node has some modules that have been compiled into binary modules that will be detailed elsewhere in this document. Introduced.

The core module is defined in the lib/folder of the Node source code.

When using require (), the core module always loads first. For example, require (' HTTP ') always returns the built-in HTTP module, even if the name of the file exists.

File module
If the exact file is not found, Node will try to give the desired file name?? Add the. js suffix to reload, and then try. Node.

The. js file is considered a JavaScript text file, and the. node file is considered a compiled plug-in module, loaded with Dlopen.

The module starts with a '/' to indicate the absolute path to the file. For example, require ('/home/marco/foo.js ') will load the/home/marco/foo.js file.

The module starts with a './' to indicate that a relative path is used when calling require (). In other words, in order to ensure that require ('./circle ') can be found, circle.js must be in the same directory as foo.js.

If you do not start with a '/' or './', the module can be a "core module" or a module that is loaded from the Node_modules folder.

Loading from the ' Node_modules ' folder
If the module identifier passed to require () is not a native module, and does not have a '/', '. /' or './', then Node tries to load from the parent directory of the current module +/node_modules this location.

If it is still not found, it jumps to the upper directory and so on, until the module is found, or until the root directory is reached.

For example, if you call require (' bar.js ') in the file '/home/ry/projects/foo.js ', then Node will look in the following location, in the order below:

/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 dependencies to prevent them from conflicting.

Optimizing the ' node_modules ' lookup process

This file lookup list can become very long when the hierarchy of nested dependencies is deep. Therefore, the following optimizations are made when looking for:

First,/node_modules is not appended to a folder that ends in/node_modules.

Second, if the file calling require () is already in a node_modules hierarchy, the topmost node_modules folder will be considered the root of the search tree.

For example, if you call require (' asdf.js ') in the file '/home/ry/projects/foo/node_modules/bar/node_modules/baz/quux.js ', then node searches for the following locations:

/home/ry/projects/foo/node_modules/bar/node_modules/baz/node_modules/asdf.js
/home/ry/projects/foo/node_modules/bar/node_modules/asdf.js
/home/ry/projects/foo/node_modules/asdf.js
Take a folder as a module
Node allows users to easily organize programs in separate directories and then provide a single entry point to the library. There are three ways to use a folder as a parameter to require ().

The first way is to create a Package.json file in the folder, specifying a main module. A typical Package.json file might look like this:

{"Name": "Some-library",
"Main": "./lib/some-library.js"}
If this file is located in the./some-library folder, require ('./some-library ') tries to load the./some-library/lib/some-library.js.

This is the case where Node can find the Package.json file.

If there is no Package.json file in the directory, then Node attempts to load the Index.js or Index.node file in that directory. For example, if the above example cannot find Package.json, then require ('./some-library ') will attempt to load:

./some-library/index.js
./some-library/index.node
Cache
The module is cached when it is first loaded. This means that every call to require (' foo ') will get exactly the same object if it is parsed into the same file.

Summarize......
To get the exact file name that was loaded when calling require (), use the Require.resolve () function.

In summary, this is the pseudo code description of Require.resolve:

Require (X)
1. If X is a core module,
A. Return the core module
B. STOP
2. If X begins with './' 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.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. Load_as_file (X/index)

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 ROOT = Index of the first instance of "Node_modules" in PARTS, or 0
3. Let I = Count of PARTS-1
4. Let DIRS = []
5. While I > ROOT,
A. If parts[i] = "Node_modules" CONTINUE
C. DIR = Path Join (parts[0. I] + "Node_modules")
B. DIRS = DIRS + DIR
6. Return DIRS
Loading from ' require.paths '
In Node, Require.paths is an array of strings that indicates that the module does not begin the search path with '/'./' or '. '. For example, if Require.paths is set to:

['/home/micheil/.node_modules ',
'/usr/local/lib/node_modules ']
The call to require (' bar/baz.js ') will search for the following location:

1: '/home/micheil/.node_modules/bar/baz.js '
2: '/usr/local/lib/node_modules/bar/baz.js '
You can modify the require.paths array at run time to change this behavior.

Its value is initially from the NODE_PATH environment variable, which is a colon-delimited list of absolute paths. In the previous example, the NODE_PATH environment variable might be set to:

/home/micheil/.node_modules:/usr/local/lib/node_modules
The require.paths is only attempted if the module is not found using the node_modules algorithm above. The global module has a lower priority than the bundle dependency.

* * NOTE * * Please do not modify ' require.paths '

For compatibility reasons, Require.paths is still the preferred strategy for the module lookup process. However, it may be deprecated in a future release.

While it may seem like a good idea, in practice a mutable list of require.paths is often the source of trouble and confusion.

Modifying ' require.paths ' is useless

This line of code is not as expected:

Require.paths = ['/usr/lib/node '];
The result is that Node's actual module lookup path reference is discarded and a useless new reference is created that points to the other.

Add relative path to ' require.paths ' ... Not a good idea.

If you do this:

Require.paths.push ('./lib ');
It does not add./lib the full path that has been resolved on the file system. Instead, it actually adds './lib ', which means that if you require (' Y.js ') in/a/b/x.js, it will look for/a/b/lib/y.js. If you later require (' Y.js ') in the/l/m/n/o/p.js, then it will look for/l/m/n/o/lib/y.js.

In practice, it is often used as a temporary solution to a bundle of dependencies, a technique that is less than secure.

0 Isolation

There is a bad design: All modules share a require.paths array.

As a result, if a node program relies on this behavior, it can permanently and subtly change the behavior of other node programs in the same process. When the complexity of the application increases, we tend to encapsulate functionality, and the hard-to-anticipate parts of these behaviors can be a nightmare for developers.

Addendum: Package Management Tips
In Node, the semantics of the require () function are designed to be generic enough to support a large number of reasonable directory structures. So package managers such as dpkg, RPM, and NPM can build native packages from the Node module without making changes.

Below we give a list of recommended directory structures to work with:

For example, we want the/usr/lib/node/<some-package>/<some-version> folder to contain the content of a particular version of a package.

A package can depend on other packages. In order to install the Foo package, you may need to install a specific version of the bar package. It is possible that the bar package itself has dependencies, and in some cases these dependencies may even conflict or form loops.

Because Node finds its true path when loading any module (that is, the symbolic link is parsed), then the Node_modules folder looks for dependencies in the way described above. The following schemas can be used to easily resolve:

/USR/LIB/NODE/FOO/1.2.3/the contents of the-foo package, version 1.2.3.
/USR/LIB/NODE/BAR/4.3.2/the contents of the-bar package, Foo relies on this package.
/usr/lib/node/foo/1.2.3/node_modules/bar-a symbolic link to the/usr/lib/node/bar/4.3.2/.
/usr/lib/node/bar/4.3.2/node_modules/*-the symbolic link to the package on which bar depends.
Therefore, even if a loop is encountered, or if there is a dependency conflict, each module is able to get the available version it relies on.

When there is code require (' bar ') in the Foo package, it gets the version of the symbolic link to/usr/lib/node/foo/1.2.3/node_modules/bar. Then, when the bar package calls require (' Quux '), it gets the version of the symbolic link to/usr/lib/node/bar/4.3.2/node_modules/quux.

In addition, in order to make the module lookup process more optimized, and?? Instead of just putting the bags in the/usr/lib/node, we can put them in the/usr/lib/node_modules/<name>/<version>. This way, Node does not have to be found in/usr/node_modules or/node_modules.

To enable REPL to reference the module normally, you can add/usr/lib/node_modules to the $NODE _path environment variable. Because the path to finding the module using the Node_modules folder is relative, and the call to require () is based on the true path of the file, the package itself can be placed in any location.

Nodejs Require execution process

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.