1. AMD Origin
Although the front-end technology is constantly evolving, there has been no qualitative leap. In addition to existing famous frameworks, such as Dojo, jquery, and extjs, many companies also have their own front-end development frameworks. The efficiency and development quality of these frameworks depend largely on the developer's familiarity with them and the degree of familiarity with JavaScript, this is why many technical leaders like to develop their own frameworks. It is not difficult to develop a framework that you will use, but it is difficult to develop a framework that everyone like. When migrating from a framework to a new framework, developers are likely to think about and solve problems based on the thinking of the original framework. One of the important reasons is the flexibility of JavaScript itself: the framework cannot absolutely constrain your behavior. One thing can always be implemented in multiple ways, therefore, we can only guide the correct implementation methods in the methodology. Fortunately, software methodology research at this level has been constantly trying and improving, and commonjs is an important organization. They proposed many new JavaScript architecture solutions and standards, hoping to provide a uniform guide for front-end development.
2. What is amd?
As a specification, you only need to define its syntax API, but do not care about its implementation. AMD specifications are as simple as only one API, that is, the define function:
Define ([module-name?], [Array-of-dependencies?], [Module-factory-or-object]);
Where:
- Module-Name: module ID, which can be omitted.
- Array-of-dependencies: the dependent module, which can be omitted.
- Module-factory-or-object: module implementation, or a JavaScript Object.
We can see that the first and second parameters can be omitted, and the third parameter is the specific implementation of the module. They will use different parameter combinations in different application scenarios.
From this define function A: asynchronous in AMD, it is not difficult to think of another nature of the define function, asynchronous. When the define function is executed, it first asynchronously calls the dependent modules listed in the second parameter. After all modules are loaded, if the third parameter is a callback function, it is executed, and then the system module is notified that its own module is available. If it corresponds to the implementation before dojo1.6, the function can have the following correspondence:
- Module-Name: dojo. Provide
- Dependencies: dojo. Require
- Module-factory: dojo. Declare
The difference is that amd uses Asynchronization when loading dependencies, while dojo. Require is synchronous. The difference between Asynchronization and synchronization is obvious. The former does not block the browser and provides better performance and flexibility. For server amd such as nodejs, module loading does not require blocking server processes, which also improves performance.
3. AMD instance: how to define a module
The following code defines an Alpha module and relies on the built-in require, exports module, and external beta module. As you can see, the third parameter is the callback function, which can be directly used by the dependent module. They are provided to the callback function as parameters in the declared order of dependency.
The require function allows you to depend on a module at any time, that is, to obtain the reference of the module, so that the module can be used even if it is not defined as a parameter; exports is the entity of the defined Alpha module. Any attributes and methods defined on it are the attributes and methods of the Alpha module. Exports. verb =... defines a verb method for the Alpha module. In this example, the verb method of the module beta is called.
Define ("Alpha", ["require", "Exports", "Beta"], function (require, exports, beta) {exports. verb = function () {return beta. verb (); // or: Return require ("Beta "). verb ();}});
4. Anonymous Module
The define method allows you to omit the first parameter, so that an anonymous module is defined. At this time, the module File Name is the module identifier. If this module File is placed in a. JS, A is the module name. You can use "A" in the dependency to depend on this anonymous module. This brings about a high degree of reusability of modules. You can use an anonymous module wherever you are. The module name is its file path. This also fits well with the dry (don't repeat yourself) principle.
The following code defines an anonymous module dependent on the Alpha module:
define(["alpha"], function (alpha) { return { verb: function(){ return alpha.verb() + 2; } };});
5. Define with only one parameter
As mentioned above, the first two parameters of define can be omitted. The third parameter can be a javascript object or a function.
If it is an object, it may be an object that contains functions of the method, or it may only provide data. The latter is very similar to the JSON-P, so amd can also be considered to include a complete JSON-P implementation. Module evolved into a simple data object, such data object is highly available, and because it is a static object, it is also CDN-friendly, can improve the performance of JSON-P. Consider a JavaScript Object that provides ing between provinces and cities in China. If it is provided to the client in the form of a traditional JSON-P, it must provide a callback function name that dynamically generates the returned data based on this function name, this makes the standard JSON-P data not CDN friendly. However, If AMD is used, the data file is in the following format:
Define ({provinces: [{Name: 'shanghai', areas: ['pudong New Area ', 'xuhui district']}, {Name: 'jiangsu ', cities: ['nanjing ', 'nantong']} // ......]});
Assume that the file name is China. js. If a module needs this data, you only need:
Define (['China', function (China) {// use Chinese provincial and municipal data here });
In this way, this module is truly highly reusable. both remote and copy-to-Local Projects save development time and maintenance time.
If a parameter is a function, one of its purposes is quick development and implementation. Applicable to small applications. You do not need to pay attention to the modules you need and who you want to use them. In a function, you can request the required modules at any time. For example:
Define (function () {var P = require ('China'); // use the China module });
That is, you omit the module name and the module you need to depend on. This does not mean that you do not need to rely on other modules. Instead, you can request these modules as needed. When the define method is executed, it will call the tostring method of the function, and scan the require call in it to help you load these modules in advance, and then execute after loading. This makes rapid development possible. It should be noted that opera does not support the tostring method of functions very well. Therefore, it is not applicable very well in the browser. However, if you use the build tool to package all JavaScript files, this will not be a problem. The build tool will help you scan require and forcibly load the dependent modules.
6. AMD in Dojo
Dojo officially released version March in early 1.6. An important change was the introduction of the amd mechanism, replacing the original dojo. Provide and dojo. Require methods. However, it still maintains backward compatibility. You can still use dojo. Provide and dojo. Require To define and load modules. It should be noted that in Dojo 1.6, amd refactoring is still a transitional change, and the amd module developed by the user cannot be supported by the dojo loader and build system. the existing compilation system in 1.6 is still very limited to AMD support. If you have developed an AMD-format module and you are still using the default dojo synchronization module loader, you must strictly follow the format of the dojo module (including the line feed format) to ensure that your module can be compiled successfully. To sum up, there are three points:
- Using the traditional method (Dojo. require ()/dojo. provide ()-These modules can only be loaded by the dojo synchronous loader, but can be correctly compiled by the dojo compilation system (build system ).
- Use the dojo synchronous loader to load AMD (define () modules. These modules can be normally loaded and loaded by other amd-compatible loaders. although dojo1.6 does not yet officially support this method, it works normally in the current dojo1.6 compilation system. (the premise is that you must strictly follow the code specifications defined by the dojo module)
- Third-party loaders are used to load AMD (define () modules. modules can be normally loaded and used by other loaders. these modules can be compiled normally using the compilation system provided by requirejs or Backdraft, but dojo has not officially tested its compatibility with other loaders.
Take calendar as an example. Use the define method to define this module:
define("dijit/Calendar", ["dojo", "dijit", "text!dijit/templates/Calendar.html", "dojo/cldr/supplemental", "dojo/date", "dojo/date/locale","dijit/_Widget", "dijit/_Templated", "dijit/_CssStateMixin", "dijit/form/DropDownButton"], function(dojo, dijit) { dojo.declare( "dijit.Calendar", [dijit._Widget, dijit._Templated, dijit._CssStateMixin], {...} ); return dijit.Calendar; });
As you can see, the module identifier is the path of the module file. The module itself is generally a class defined by dojo. Declare. Modules in the dojo and dijit namespaces in dojo1.6 have been reconstructed in the form of AMD, but the traditional forms of dojo. Provide and dojo. Require are still used in dojox. The introduction of AMD is an important step for dojo to automate package management. We will continue to pay attention to the development of dojo in subsequent articles.
7. Conclusion
AMD specification is an important attempt in Javascript development. It unifies the module definition and loading mechanism of Javascript in a simple and elegant way, and is quickly recognized and adopted by many frameworks. This is good news for developers. with AMD, We have lowered the threshold for learning and using various frameworks, and can define and use modules in a unified way to improve development efficiency, reduces application maintenance costs.
References:
Dojo Chinese Blog
Requirejs/AMD module forms
Modules/asynchronousdefinition
This article has been launched on the infoq Chinese site and is copyrighted. The original Article is "dojo1.6 new features: Talking about AMD specifications". If you need to reprint it, please attach this statement. Thank you.
Infoq Chinese site is an online independent community for mid-and high-end technical personnel ,. net, Ruby, SOA, agility, architecture and other fields to provide timely and in-depth information, high-end technology conferences such as qcon, offline technology exchange activities qclub, free mini book download such as architect, etc..