This is the voa Special English Health Report
  • Tags:
  • javascript /
  • Modular /
  • The front end
  • 21234

Recently in the research of CMD and AMD, I saw a good article on the Internet, sort it out and have a look. In the early development of JavaScript is to achieve simple page interaction logic, just a few words; Nowadays, CPU and browser performance have been greatly improved, and a lot of page logic has been migrated to the client (form verification, etc.). With the advent of Web2.0 era, Ajax technology has been widely used, jQuery and other front-end libraries emerge in endlessly, and front-end code is expanding day by day

At this point, JavaScript’s position as an embedded scripting language is shaken, but JavaScript offers no obvious help in organizing code, not even the concept of classes, let alone modules. JavaScript’s extremely simple code organization specification is not enough to handle such a large scale of code

The module

Since JavaScript cannot handle such a large amount of code, we can learn how other languages handle large-scale programming. In Java, there is an important concept called package. Logically related code is organized into the same package, which is a relatively independent kingdom. Don’t worry about naming conflicts or anything, but what about external use? Import the corresponding package directly

import java.util.ArrayList; Unfortunately, JavaScript was designed for reasons other than providing similar functionality, and developers need to simulate similar functionality to isolate and organize complex JavaScript code, which we call modularity.

A module is a file that implements a particular function. With a module, we can more easily use other people’s code and load whatever function we want. Module development needs to follow a certain set of rules, and everything goes wrong

The process of the formation of norms is painful. The pioneers of the front end began in the stage of slash-and-burn farming and drinking blood, and developed to take shape now. A brief understanding of this extraordinary process

Function encapsulation

When we talked about functions, we mentioned that a function is a package of statements that implement specific logic, and JavaScript’s scope is based on functions, so it’s a natural first step to modularize functions. Writing several related functions in a file is the beginning of a module

function fn1(){
    statement
}

function fn2(){
    statement
}1234567Copy the code

In this way, after the need to clip the function in the file, call the function can be

The disadvantages of this approach are obvious: it contaminates global variables, there is no guarantee of variable name conflicts with other modules, and there is little relationship between module members.

object

In order to solve the above problem, the object writing method came into being, you can encapsulate all module members in one object

var myModule = {
    var1: 1,

    var2: 2,

    fn1: function(){

    },

    fn2: function(){

    }
}12345678910111213Copy the code

So we reference the corresponding file whenever we want to call the module, and then

myModule.fn2(); This avoids variable contamination, as long as the module name is unique and members of the same module are related

This may seem like a good solution, but it has a downside: outsiders can modify internal members at will

myModel.var1 = 100; This can create unexpected security problems

Execute function immediately

You can hide the details by executing the function immediately

var myModule = (function(){
    var var1 = 1;
    var var2 = 2;

    function fn1(){

    }

    function fn2(){

    }

    return{ fn1: fn1, fn2: fn2 }; }) (); 1234567891011121314151617Copy the code

This makes it impossible to modify variables or functions outside the module that are not exposed

This is the basis for our modularity. Currently, there are two common JavaScript module specifications: CommonJS and AMD

CommonJS

We will start with CommonJS, because there is no modular programming on the web side, but JavaScript logic is complicated, but it can work, but there must be modules on the server side, so although JavaScript has been developed on the Web side for so many years, The first popular modularity specification came from server-side JavaScript applications. The CommonJS specification was carried forward by NodeJS, which marked the formal arrival of JavaScript modularity programming.

According to the CommonJS specification, a single file is a module. Each module is a separate scope, that is, variables defined inside the module cannot be read by other modules unless they are defined as properties of the Global object

Module output: The module has only one export, module.exports object, into which we need to put what the module wants to export

3. Load modules: Load modules using the require method, which reads a file and executes, returning the module.exports object inside the file

Look at an example

// Mymodel.js var name ='Byron';

function printName(){
    console.log(name);
}

function printFullName(firstName){
    console.log(firstName + name);
}

module.exports = {
    printName: printName,
    printFullName: printVar nameModule = require(FullName)'./myModel.js'); nameModule.printName(); 12345678910111213141516171819202122Copy the code

Different implementations require different paths. In general, js extensions can be omitted, relative paths can be used, absolute paths can be used, and even the module name can be omitted (provided that the module is a built-in module of the system).

Awkward Browser

If you look closely at the code above, you’ll see that require is synchronous. The module system needs to read the contents of the module file synchronously and compile the execution to get the module interface.

This is easy and natural to implement on the server side, however, there are many problems to implement on the browser side.

On the browser side, the best and easiest way to load JavaScript is to insert script tags in document. But script tags are inherently asynchronous, and traditional CommonJS modules don’t load properly in a browser environment.

One solution is to develop a server-side component that statically analyzes the module code and returns the module to the browser side with a list of its dependencies. This works fine, but requires additional components to be installed on the server and a series of underlying architectures to be adjusted as a result.

Another solution is to encapsulate module definitions with a standard set of templates, but there are disagreements about how modules should be defined and loaded:

AMD

AMD is an Asynchronous Module Definition. It is a specification for modular development on the browser side

Because it is not JavaScript native support, page development using AMD specification needs to use the corresponding library function, also known as RequireJS. In fact, AMD is the standardization of module definition of RequireJS in the promotion process

RequireJS addresses two main problems

1. Multiple JS files may have dependencies, and the dependent file must be loaded before the dependent file is loaded into the browser. 2

Mymodule.js define(['dependency'].function(){
    var name = 'Byron';
    function printName(){
        console.log(name);
    }

    return {
        printName: printName }; }); // require(['myModule'].function (my){
  my.printName();
});12345678910111213141516Copy the code

grammar

RequireJS defines a function define, which is the global variable used to define the module

define(id? , dependencies? , factory);

  1. Id: Optional parameter used to define the identity of the module. If this parameter is not provided, the name of the script file (without the extension)
  2. Dependencies: Is an array of module names that the current module depends on
  3. Factory: A factory method that a module initializes a function or object to execute. If it is a function, it should be executed only once. If it is an object, the object should load the module on the page using the require function for its output value

require([dependencies], function(){}); The require() function takes two arguments

  1. The first argument is an array representing the dependent module
  2. The second argument is a callback function that will be called after all the modules specified in the previous page have been successfully loaded. Loaded modules are passed to the function as arguments, so they can be used inside the callback function

The require() function is asynchronously loaded when loading dependent functions, so that the browser does not lose response, and it specifies a callback function that will not run until all previous modules have been successfully loaded.

CMD

CMD is the Common Module Definition, CMD specification is developed in China, just as AMD has a requireJS, CMD has a browser implementation SeaJS, SeaJS to solve the same problem as requireJS, The sea-js syntax is defined in the way modules are defined and when modules are loaded (so to say run, parse). , deps? Factory) because CMD canonized

  1. Each file is a module, so the file name is often used as the module ID
  2. CMD advocates nearby dependencies, so you don’t write dependencies in define parameters, you write dependencies in Factory

Factory is a function that takes three arguments, function(require, exports, module)

  1. Require is a method that takes a module id as a unique argument to get the interface provided by other modules: require(ID)
  2. Exports is an object that provides module interfaces
  3. A module is an object that stores properties and methods associated with the current module

Here’s an example:

// define module mymodule.js define(function(require, exports, module) {
  var $ = require('jquery.js'The $()'div').addClass('active'); }); Seajs.use ([)'myModule.js'].function(my){ }); 12345678910Copy the code

AMD is different from CMD

There’s a bunch of articles on the Internet about the difference between the two, just to summarize it

The most obvious difference is the way dependencies are treated in module definition

CMD advocates nearby dependency, requiring only when a module is used. This distinction has its advantages and disadvantages, but there is a gap in syntax. RequireJS and SeaJS both support each other’s writing methods

The biggest difference between AMD and CMD is that the execution time of dependent modules is handled differently, not the loading time or the way

It is not correct to say that requireJS and SeaJS load modules asynchronously. In fact, all modules load asynchronously, but AMD relies on the front, js can easily know who the dependent module is, and load immediately, while CMD relies on the nearby module. The need to parse modules into strings to know which modules depend on is also one of the many complaints about CMD, sacrificing performance for ease of development, and in fact the time spent parsing modules is negligible

Why we say that the difference between the two is the dependency module execution timing, and why many people think that ADM is asynchronous and CMD is synchronous (except for the name…).

Also are asynchronous loading module, AMD after completion of the loading modules will be executed to change module, all modules loaded after the execution will enter the require of the callback function, implement the main logic, the effect is dependent on module order execution order, and do not necessarily consistent, the network speed, which first download, which performed first, But the main logic must not be executed until all dependencies have been loaded

CMD does not execute a dependent module after loading it, but only downloads it. After loading all dependent modules, enter the master logic and execute the corresponding module when encountering the require statement. In this way, the execution order of modules is exactly the same as the writing order

This is why many people say that AMD has a good user experience because there is no latency, dependencies are executed ahead of time, and CMD performance is good because it is executed only when the user needs it