Parts 1 and 2 of this series introduced Javascript module prototypes and theoretical concepts, and today we introduce how to use them in practice.
I use a very popular library require.js.
1. Why use require.js?
In the earliest days, all Javascript codes were written in one file, and it was enough to load this one file. Later, there were more and more codes, and one file was no longer enough. It had to be divided into multiple files and loaded in sequence. I believe many people have seen the web page code below.
< script src="4.js">
This code loads multiple js files in sequence.
This way of writing has big disadvantages. First of all, when loading, the browser will stop rendering the web page. The more files are loaded, the longer the web page will lose response. Secondly, due to the dependencies between js files, the loading order must be strictly guaranteed (such as the above example) 1.js should be in front of 2.js), and the module with the greatest dependency must be loaded last. When the dependencies are complex, code writing and maintenance will become difficult.
require.js was born to solve these two problems :
(1) Implement asynchronous loading of js files to avoid web page loss of response;
(2) Manage dependencies between modules to facilitate code writing and maintenance.
2. Loading require.js The first step to use require.js is to download the latest version from the official website.
After downloading, it is assumed that it is placed under the js subdirectory and it can be loaded.
Some people may think that loading this file may also cause the web page to lose response. There are two solutions, one is to load it at the bottom of the web page, the other is to write it as follows:
The async attribute indicates this file It needs to be loaded asynchronously to avoid the web page becoming unresponsive. IE does not support this attribute and only supports defer, so defer is also written.
After loading require.js, the next step is to load our own code. Assume that our own code file is main.js and is also placed under the js directory. Then, just write it as follows:
< script src="js/require.js" data-main="js/main">
The data-main attribute is used to specify the main module of the web program. In the above example, it is main.js under the js directory. This file will be loaded by require.js first. Since the default file extension of require.js is js, main.js can be abbreviated to main.
3. How to write the main module The main.js in the previous section, I call it the "main module", which means the entry code of the entire web page. It's a bit like the main() function in C language, all code starts running from here.
Let’s see how to write main.js.
If our code does not depend on any other modules, we can write javascript code directly.
// main.js
alert("Loading Success! ");
But in this case, there is no need to use require.js. A really common situation is that the main module depends on other modules, in which case the require() function defined by the AMD specification must be used.
// main.js
require([' moduleA', 'moduleB', 'moduleC'], function (moduleA, moduleB, moduleC){
// some code here
});
require() function accepts two parameters. The first parameter is an array, indicating the modules it depends on. The above example is ['moduleA', 'moduleB', 'moduleC'], that is, the main module depends on these three modules; the second parameter is a callback function. Currently It will be called after all the modules specified above are loaded successfully. Loaded modules will be passed into this function as parameters, so these modules can be used inside the callback function.
require() loads moduleA, moduleB and moduleC asynchronously, and the browser will not lose response; the callback function it specifies will only run after the previous modules are loaded successfully, solving the dependency problem.
Below, we look at a practical example.
Assuming that the main module depends on the three modules of jquery, underscore and backbone, main.js can be written like this:
require(['jquery', 'underscore', 'backbone'], function ($, _, Backbone){
// some code here
} );
require.js will first load jQuery, underscore and backbone, and then run the callback function. The code of the main module is written in the callback function.
4. Module loading In the last example of the previous section, the dependent modules of the main module are ['jquery', 'underscore', 'backbone']. By default, require.js assumes that these three modules are in the same directory as main.js, with the file names being jquery.js, underscore.js and backbone.js, and then loads them automatically.
Using the require.config() method, we can customize the loading behavior of the module. require.config() is written at the head of the main module (main.js). The parameter is an object, and the paths attribute of this object specifies the loading path of each module.
require.config({
Paths: {
"jquery": "jquery.min",
"underscore": "underscore.min",
"backbone": "backbone.min"
});
The above code gives the file names of the three modules. The path defaults to the same directory as main.js (js subdirectory). If these modules are in other directories, such as the js/lib directory, there are two ways to write them. One is to specify the paths one by one.
require.config({
Paths: {
"jquery": "lib/jquery.min",
"underscore": "lib/underscore.min",
"backbone": "lib/backbone.min"
}
});
The other is to directly change the base directory (baseUrl).
require.config({
baseUrl: "js /lib",
paths: {
"jquery": "jquery.min",
"underscore": "underscore.min",
"backbone": "backbone.min"
}
});
If a module is on another host, you can also specify its URL directly, such as:
require.config({
paths: {
"jquery": "https://ajax .googleapis.com/ajax/libs/jquery/1.7.2/jquery.min"
}
});
require.js requires that each module is a separate js file. In this case, if multiple modules are loaded, multiple HTTP requests will be issued, which will affect the loading speed of the web page. Therefore, require.js provides an optimization tool. After the module is deployed, you can use this tool to merge multiple modules into one file to reduce the number of HTTP requests.
5. How to write AMD modules The modules loaded by require.js adopt AMD specifications. In other words, the module must be written according to AMD's regulations.
Specifically, the module must be defined using a specific define() function. If a module does not depend on other modules, it can be defined directly in the define() function.
Assume that there is a math.js file, which defines a math module. Then, math.js should be written like this:
// math.js
define(function (){
var add = function (x,y){
return x y;
};
return {
add: add
};
});
The loading method is as follows:
// main.js
require(['math'], function (math){
alert(math.add(1,1));
}) ;
If this module also depends on other modules, then the first parameter of the define() function must be an array indicating the dependencies of the module.
define(['myLib'], function(myLib) {
Function foo(){
myLib.doSomething();
return {
return { foo : foo
};
});
When the require() function loads the above module, the myLib.js file will be loaded first.
6. Loading non-standard modules
Theoretically, modules loaded by require.js must be modules defined with the define() function in accordance with AMD specifications. But in fact, although some popular function libraries (such as jQuery) already comply with the AMD specification, many more libraries do not.
So, can require.js load non-standard modules? The answer is yes.
Before loading such modules with require(), you must first use the require.config() method to define some of their characteristics. For example, the two libraries underscore and backbone are not written using AMD specifications. If you want to load them, you must first define their characteristics.
shim: {
| 'underscore': {
exports: '_'
| },
'backbone': {
| 'jquery'],
bone '
}
}
});
require.config() accepts a configuration object. In addition to the paths attribute mentioned earlier, this object also has a The shim attribute is specially used to configure incompatible modules. Specifically, each module must define (1) the exports value (output variable name), which indicates the name of the module when called externally; (2) the deps array, which indicates the dependencies of the module.
For example, the jQuery plug-in can be defined like this:
'jquery.scroll': {
deps: ['jquery'],
exports: 'jQuery.fn.scroll'
}
}
7. require.js plug-in
require.js also provides a series of plug-ins to implement some specific functions.
The domready plug-in allows the callback function to run after the page DOM structure is loaded. // called once the DOM is ready
});
The text and image plug-ins allow require.js to load text and image files.
define([
text!review.txt ',
'image!cat.jpg'
],
function(review,cat){
console.log(review);
document.body.appendChild(cat);
}
);
Similar plug-ins include json and mdown, which are used to load json files and markdown files.
(End)