Node. js development from scratch (2)-Use of require

Source: Internet
Author: User

The most common require Method
Require ('http') built-in Module

Require ('./Server') "./" indicates the current path, followed by the relative path
Require ("../lib/server") ../indicates the upper-level directory, followed by a relative path


Server. js

[Javascript]
Var http = require ('http ');
Function start (){
Server = http. createServer (function (req, res ){
Res. writeHeader (200, {"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 actual situation.
Var server = require ("./learnNode/server ");
Server. start ();

The following introduces require only 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, files correspond to modules one by one. For example, in foo. js, load the circle. js module in the same directory.

Foo. js content:

Var circle = require ('./circle. js ');
Console. log ('the area of a circle of radius 4 is'
+ Circle. area (4 ));
Contents of circle. js:

Var PI = Math. PI;

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

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

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

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

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

When require () is used, core modules are always preferentially loaded. For example, require ('http') always returns the built-in http module, even if the file with this name exists.

File Module
If no exact file is found, Node will try to add a. js suffix to the file name and then load it, And then try. node.

. Js files are considered JavaScript text files, while. node files are considered compiled plug-in modules and loaded with dlopen.

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

The relative path is used when the module starts with './' to call require. That is to say, to ensure that require ('./circle') can be found, circle. js AND foo. js must be in the same directory.

If it does not start with '/' or './', this module can be a "core module" or a module loaded from the node_modules folder.

Load from the 'node _ modules' folder
If the module identifier passed to require () is not a native module, and it is not '/','.. /'or '. /', then the Node tries to load from the parent directory of the current module +/node_modules.

If it is still not found, it will jump to the upper directory and push it accordingly until it finds the module or reaches the root directory.

For example, if you call require ('bar. js') in the '/home/ry/projects/foo. js' file, the Node will be searched in the following locations in the 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 dependencies to prevent conflicts.

Optimize the 'node _ modules' search process

When the hierarchy of the nested dependency is very deep, the file search list may become very long. Therefore, perform the following optimization during search:

First,/node_modules is not appended to a folder ending with/node_modules.

Second, if the file that calls require () is already in a node_modules level, the node_modules folder at the top is considered as the root of the search tree.

For example, if the file '/home/ry/projects/foo/node_modules/bar/node_modules/baz/quux. call require ('asdf. js '), then Node will search 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
Use folders as modules
Node allows you to easily organize programs in a separate directory, and then provides a single entry pointing to the library. There are three ways to use folders as the require () parameter.

The first method is to create a package. json file in the folder and specify a main module. A typical package. json file may look like this:

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

This is where Node can find the package. json file.

If there is no package. json file in this directory, Node will try to load the index. js or index. node file in this directory. For example, if package. json is not found in the preceding example, require ('./some-library') will try to load:

./Some-library/index. js
./Some-library/index. node
Cache
The module is cached after being loaded for the first time. This means that each call to require ('foo') will get the same object if it is resolved to the same file.

Conclusion ......
To obtain the exact file name loaded when require () is called, use the require. resolve () function.

To sum up, 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 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
Load from 'require. paths'
In Node, require. paths is a string array, indicating that the module does not start with '/'./'or. For example, if require. paths is set:

['/Home/micheil/. node_modules ',
'/Usr/local/lib/node_modules']
Call require ('bar/baz. js') to search for the following locations:

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 runtime to change this behavior.

Its value is initially derived from the NODE_PATH environment variable, which is an absolute path list separated by colons. In the previous example, the NODE_PATH environment variable may be set:

/Home/micheil/. node_modules:/usr/local/lib/node_modules
Require. paths will be attempted only when the module cannot be found using the node_modules algorithm above. The priority of a global module is lower than that of a bound dependency.

** Note ** do not modify 'require. paths'

For compatibility considerations, require. paths is still the first choice in the module search process. However, it may be discarded in future versions.

Although it seems to be a good idea, in practice, a variable require. paths list 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 the actual module path reference of Node is discarded, and a new reference pointing to other places is created.

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

If you do this:

Require. paths. push ('./lib ');
It does not add./lib to the complete resolved path on the file system. Instead, it actually adds '. /lib ', which means that if you are in/a/B/x. require ('Y. js '), then it will find/a/B/lib/y. js. If you are later at/l/m/n/o/p. require ('Y. then it will find/l/m/n/o/lib/y. js.

In practice, people often use it as a temporary solution to bundling dependencies. This technique is not secure.

Zero isolation

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

As a result, if a Node program depends on this behavior, it may permanently and implicitly change the behavior of other Node programs in the same process. When the complexity of applications increases, we tend to encapsulate features. The unpredictable parts of these behavior will become a nightmare for developers.

Addendum: software package management tips
In Node, the semantics of the require () function is designed to be universal enough to support a large number of reasonable directory structures. Therefore, package managers such as dpkg, rpm, and npm can build native packages from the Node module without making changes.

The following shows a directory structure that can work:

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

A software package can depend on other packages. To install the foo package, you may need to install a specific version of the bar package. The bar package may have dependencies. In some cases, these dependencies may even conflict or form a loop.

Node will find its actual path (that is, it will parse the symbolic link) when loading any module, and then search for dependencies in the node_modules folder in the way described above. The following architecture can be easily solved:

The content of the/usr/lib/node/foo/1.2.3/-foo package, version 1.2.3.
The content of the/usr/lib/node/bar/4.3.2/-bar package. foo depends on this package.
/Usr/lib/node/foo/1.2.3/node_modules/bar-to/usr/lib/node/bar/4.3.2.
/Usr/lib/node/bar/4.3.2/node_modules/*-symbolic link to the package on which bar depends.
Therefore, even if a loop or dependency conflict occurs, each module can obtain the available version on which it depends.

When the foo package contains the Code require ('bar'), it will get a symbolic link to the/usr/lib/node/foo/1.2.3/node_modules/bar version. Then, when the bar package calls require ('quux '), it will get a symbolic link to the/usr/lib/node/bar/4.3.2/node_modules/quux version.

In addition, in order to optimize the module search process, instead of directly placing the package in/usr/lib/node, we can put them in/usr/lib/node_modules/<name>/<version>. In this way, Node does not need to be searched in/usr/node_modules or/node_modules.

To enable REPL to reference modules normally, you can add/usr/lib/node_modules to the $ NODE_PATH environment variable. Because the path used to search for a module in the node_modules folder is relative and the actual path based on the file when require () is called, the package itself can be placed anywhere.

 

Related Article

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.