Getting started with js framework require. js

Source: Internet
Author: User
Tags min parent directory

Introduction to require. js

RequireJS is a tool library mainly used for client module management. It divides the client code into modules for asynchronous or dynamic loading, thus improving the code performance and maintainability. Its module management complies with AMD specifications. Modules and modules can depend on each other. Of course, some may think that the dependencies between modules cannot be correctly loaded in a specific order, the AMD specification can handle this problem. AMD defines the module so that the module and its dependencies can be asynchronously loaded, but in the correct order.

AMD stands for "Asynchronous Module Definition", which means "Asynchronous Module Definition ". The module is loaded asynchronously. The module loading does not affect the execution of the subsequent statements. All statements that depend on this module are defined in a callback function. After loading is complete, the callback function will run.

How to use require. js?

Download require. js and embed it into the webpage,

<Script data-main = "scripts/main" src = "scripts/require. js"> </script>

The data-main attribute declares the entry File scripts/main. js. Here we omit the. js suffix. There are also the following statements:

<Script src = "scripts/require. js" data-main = "scripts/main" defer async = "true"> </script>

The async attribute indicates that the file needs to be asynchronously loaded to avoid webpage response loss. IE does not support this attribute and only supports defer. Therefore, defer is also supported. At the same time, the official require. js and jquery package versions are provided, so how can we introduce them:

<Script src = "scripts/require-jquery.js" data-main = "scripts/main" defer async = "true"> </script>

RequireJS defines the code as a module through the define method, and implements code module loading through The require method.

By using the define method, you can write the code in a js file and separate it as a module. For example, I create an animate module (animate. js), as shown below:


Define (function (){
Function animate (){
This. name = "animate ";
};
Return {
Animate: animate,
Dec: "This is a description"
};
})


Place your module code in define (function () {/* code */}); and then expose the return object of the module, when other modules can depend on this module, they can call the API of this module. For example, we create a tabview module (tabview. js) to depend on this animate module,


Define (['imase'], function (){
Function tabview (){
This. name = 'tabview ';
This. animate = a. animate. name;
This. dec = a. dec;
    }
Return {tabview: tabview };
})



Analyze the code above, introduce the animate module, and assign it an alias for. So can this module call the methods and attributes in the animate module?

Here we create a treeview module (treeview. js) as follows:

Define (function (){
Function treeview (){
This. name = "treeview ";
};
Return {treeview: treeview };
})

Next, we need to use the previously defined module to implement the require method. For details, see the description in main. js, as shown below:


Require (['tabview', 'treeview'], function (a, B ){
Var tab = new a. tabview ();
Var tree = new B. treeview ();
Alert (tab. name );
Alert (tab. animate );
Alert (tab. dec );
Alert (tree. name );
});



This method is used to load the tabview and treeview modules. The tabview module depends on the animate module. Because the module returns all objects, we can call the methods and attributes of the loading module with a new object!

In main. js, we need to configure the module path. In the example above, we need to configure the paths of several modules as follows:


Require. config ({
Paths :{
"Tabview": "js/tabview ",
"Animate": "js/animate ",
"Treeview": "js/treeview"
}
});

// Another method is to directly change the base directory (baseUrl ). Suffix. js can be omitted
Require. config ({
BaseUrl: "js/lib ",
Paths :{
"Jquery": "jquery. min ",
"Underscore": "underscore. min ",
"Backbone": "backbone. min"
}
});



In this way, require. js can be used flexibly for modular management. Here is a web component (pop-up demo) built based on require. js. It is worth learning! You can check it out! Github: https://github.com/xiaobinwu/require.js-Popup-window-


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

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

// The path depends on your actual situation.
Var server = require ("./learnNode/server ");
Server. start ();

The following describes require.


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.


Summary

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.

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.