JavaScript Modular Development

Keywords: Front-end JQuery Javascript github less

What is modular development?

In front-end development, it can achieve some basic interaction effect as long as several dozens or hundreds of lines of code are embedded in script tags at first. Then js is valued and widely used. The help of jQuery, Ajax, Node.Js, MVC, MVVM, etc. also makes front-end development important and makes front-end projects more complex. However, JavaScript does not provide any clear information for organization code.Explicitly helpful, even without the concept of a class, let alone a module, what is a module?

A module is a file that implements a specific function. With a module, we can use other people's code more easily and load any module we want.Module development needs to follow certain specifications, otherwise they are all messy.

According to the AMD specification, we can use define to define modules and require to invoke modules.

Currently, there are two main js module specifications: CommonJS and AMD.

AMD Specification

AMD is Asynchronous Module Definition. The Chinese name means Asynchronous Module Definition.It is a specification for modular development on the browser side and a specification on the server side is CommonJS

Modules are loaded asynchronously, and module loading does not affect the operation of subsequent statements.All statements that depend on certain modules are placed in callback functions.

AMD is the standardization of module definitions by RequireJS in the promotion process.

define() function

The AMD specification defines only one function, define, which is a global variable.The function is described as:

define(id?, dependencies?, factory);

Parameter description:

id: The name of the module in the definition is optional; if this parameter is not provided, the name of the module should default to the name of the specified script requested by the module loader.If this parameter is provided, the module name must be "top-level" and absolute (relative names are not allowed).

Dependency dependencies: An array literal quantity that is dependent on the current module and identified by the module defined by the module.
Dependency parameter is optional and should default to ['require','exports','module'] if omitted.However, if the length property of the factory method is less than 3, the loader chooses to call the factory method with the number of parameters specified by the length property of the function.

Factory method factory, module initializes the function or object to be executed.If it is a function, it should only be executed once.If it is an object, it should be the output value of the module.

Format of module name

Module names are used to uniquely identify the modules in the definition, which are also used in dependency arrays:

The module name is a string of meaningful words separated by a forward slash
The word must be in the form of a hump, or "." "
Module names do not allow file extensions such as'.js'
The module name can be "relative" or "top-level".Relative module name if the first character is'. 'or'.'.
Top-level module names are resolved from the conceptual module of the root namespace
Relative module names are resolved from modules written and invoked by "require"

Use require and exports

Create a module named "alpha" using require, exports, and a module named "beta":

 define("alpha", ["require", "exports", "beta"], function (require, exports, beta) {
       exports.verb = function() {
           return beta.verb();
           //Or:
           return require("beta").verb();
       }
   });


Request API Introduction: https://github.com/amdjs/amdj...

Chinese version of AMD specification: https://github.com/amdjs/amdj...

Currently, the libraries that implement AMD are RequireJS, curl, Dojo, Nodules, and so on.

CommonJS specification

CommonJS is a specification for server-side modules that Node.js uses.Node.JS first adopted the concept of JS modularization.

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

The best way to output module variables is to use the module.exports object.

var i = 1;
var max = 30;

module.exports = function () {
  for (i -= 1; i++ < max; ) {
    console.log(i);
  }
  max *= 1.1;
};

The code above defines a function through the module.exports object that serves as a bridge between internal and external communication of the module.

Loading a module uses the require method, which reads a file, executes it, and returns the module.exports object inside the file.

CommonJS specification: http://javascript.ruanyifeng....

RequireJS and SeaJS

RequireJS was created by James Burke, who was also the founder of the AMD specification.

The define method is used to define modules, and RequireJS requires that each module be placed in a separate file.

RequireJS and Sea.js are both module loaders and advocate the concept of modular development. The core value is to make the modular development of JavaScript simple and natural.

The biggest difference between SeaJS and RequireJS is:

SeaJS's attitude towards modules is lazy, while RequireJS's attitude towards modules is pre-execution

Don't get it?Look at this picture-rich article: http://www.douban.com/note/28...

RequireJS API:http://www.requirejs.cn/docs/...

Usage of RequireJS: http://www.ruanyifeng.com/blo...

Why requireJS should be used

Imagine that if a web page has many js files, the browser will load the js files when it downloads the page, stopping the rendering of the web page, and the browser may lose its response if there are more files.Secondly, to ensure the dependency of the js file, the most dependent module (file) is placed in the last load, when the dependency relationship is complex, the code writing and maintenance will become difficult.

RequireJS was born to solve these two problems:

(1) Implement asynchronous loading of js files to prevent web pages from losing responsiveness;
(2) Manage dependencies between modules to facilitate code writing and maintenance.

RequireJS file download: http://www.requirejs.cn/docs/...

AMD and CMD

CMD (Common Module Definition) generic module definition.The specification defines the basic writing format and basic interaction rules of the module.This specification was developed domestically.AMD is the dependency front-end and CMD is loaded on demand.

In the CMD specification, a module is a file.The code is written in the following format:

define(factory);


When factory is a function, the representation is the construction method of the module.By executing this construction method, you can get the interface that the module provides to you.When the factory method executes, three parameters are passed in by default: require, exports, and module:

define(function(require, exports, module) {

  // Module Code

});

A require is a parameter that can be imported into other modules, while an export can export some properties and methods within a module.
CMD Specification Address: https://github.com/seajs/seaj...

AMD is the standardized output defined by RequireJS for modules in the promotion process.
CMD is the standardized output defined by SeaJS for module in the promotion process.

For dependent modules, AMD is early execution and CMD is delayed execution.

AMD: Early Execution (Asynchronous Loading: Dependent First Execution) + Delayed Execution
CMD: Delayed execution (run to load, sequentially)

CMD esteems dependence near, AMD esteems dependence front.See the following code:

// CMD
define(function(require, exports, module) {
var a = require('./a')
a.doSomething()
// 100 lines omitted here
var b = require('./b') // Dependency Writes Nearby
b.doSomething()
// ... 
})

// AMD recommends by default
define(['./a', './b'], function(a, b) { // Dependencies must be written in the beginning
a.doSomething()
// 100 lines omitted here
b.doSomething()
...
}) 

Another difference is:

AMD: APIs differ by scope of use, but use the same api interface
CMD: Each API has a single responsibility

The advantage of AMD is that asynchronous parallel loading does not cause errors under the AMD specification.
The mechanism of CMD is different, this loading method will produce errors, if the content form of the module can be normalized, also can

Versions above jQuery 1.7 will be automatically modular and support AMD mode: mainly using the define function, sea.js is a CommonJS specification, but define is used to define modules
So jQuery is already automatically modular

seajs.config({

'base':'/',

'alias':{

    'jquery':'jquery.js'//Define a jQuery file

}
});

The define function is similar to the define of AMD:

define(function(require, exports, module{

     //Load jQuery's module first

     var $ = require('jquery');

     //Then pass the jQuery object to the plug-in module

     require('./cookie')($);

     //Start using the $.cookie method

});

How does sea.js work?

 - Introduce sea.js Library of
 - How to become a module?
      - define
 - 3.How do I invoke a module?
      -exports
      -sea.js.use
 - 4.How do I depend on modules?
      -require

 <script type="text/javascript">
        define(function (require,exports,module) {
            //Export: external interface
            //requires: Dependent interfaces
            require('./test.js');//If the address is a module, require returns exports from the module
        })
</script> 

Example of sea.js development

 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Modular Development Practice of Mouse Dragging</title>
<style type="text/css">
#div1{ width:200px; height:200px; background:black; position:absolute; display:none;}
#div2{ width:30px; height:30px; background:yellow; position:absolute; bottom:0; right:0;}
#div3{ width:100px; height:100px; background:blue; position:absolute; right:0; top:0;}
</style>
<script type="text/javascript" src="./sea.js"></script>
<script type="text/javascript">
    
//A Colleague:
seajs.use('./main.js');
    
</script>
</head>

<body>
<input type="button" value="Determine" id="input1" />
<div id="div1">
    <div id="div2"></div>
</div>
<div id="div3"></div>
</body>
</html>

A Colleague

//A Colleague's main.js:

define(function (require,exports,module) {
    var oInput = document.getElementById('input1');
    var oDiv1 = document.getElementById('div1');
    var oDiv2 = document.getElementById('div2');
    var oDiv3 = document.getElementById('div3');

    require('./drag.js').drag(oDiv3);
    oInput.onclick = function () {
        oDiv1.style.display = 'block';
        require('./scale.js').scale(oDiv1,oDiv2);

        require.async('./scale.js', function (ex) {
            ex.scale(oDiv1,oDiv2);
        })
    }
});

B Colleagues


//Dra.js written by colleague B:

define(function(require,exports,module){
    
    function drag(obj){
        var disX = 0;
        var disY = 0;
        obj.onmousedown = function(ev){
            var ev = ev || window.event;
            disX = ev.clientX - obj.offsetLeft;
            disY = ev.clientY - obj.offsetTop;
            
            document.onmousemove = function(ev){
                var ev = ev || window.event;


                 var L = require('./range.js').range(ev.clientX - disX , document.documentElement.clientWidth - obj.offsetWidth , 0 );
                 var T = require('./range.js').range(ev.clientY - disY , document.documentElement.clientHeight - obj.offsetHeight , 0 );

                
                obj.style.left = L + 'px';
                obj.style.top = T + 'px';
            };
            document.onmouseup = function(){
                document.onmousemove = null;
                document.onmouseup = null;
            };
            return false;
        };
    }
    
    exports.drag = drag;//Provide interface to external
    
});

C Colleagues

//scale.js written by colleague C:

define(function(require,exports,module){
    
    
    function scale(obj1,obj2){
        var disX = 0;
        var disY = 0;
        var disW = 0;
        var disH = 0;
        
        obj2.onmousedown = function(ev){
            var ev = ev || window.event;
            disX = ev.clientX;
            disY = ev.clientY;
            disW = obj1.offsetWidth;
            disH = obj1.offsetHeight;
            
            document.onmousemove = function(ev){
                var ev = ev || window.event;
                
                var W = require('./range.js').range(ev.clientX - disX + disW , 500 , 100);
                var H = require('./range.js').range(ev.clientY - disY + disH , 500 , 100);
                
                obj1.style.width = W + 'px';
                obj1.style.height = H + 'px';
            };
            document.onmouseup = function(){
                document.onmousemove = null;
                document.onmouseup = null;
            };
            return false;
        };
        
    }
    
    exports.scale = scale;
    
});

D Colleague

// Colleague Drange.js--Limit drag range

    define(function(require,exports,module){
        
        function range(iNum,iMax,iMin){
            
            if( iNum > iMax ){
                return iMax;
            }
            else if( iNum < iMin ){
                return iMin;
            }
            else{
                return iNum;
            }
            
        }
        
        exports.range = range;
        
    });

requirejs development example

Request.config is used to define aliases, which are configured under the paths property.Then through requirejs (parameter one, parameter two); parameter one is an array, passing in the name of the module we need to reference, parameter two is a callback function, which passes in a variable instead of the module we just introduced.

main.js file

//Alias Configuration
requirejs.config({
    paths: {
        jquery: 'jquery.min' //You can omit.js
    }
});
//Introduce a module, using variable $to represent a jquery module
requirejs(['jquery'], function ($) {
    $('body').css('background-color','red');
});

Introducing a module can also write require().requirejs defines modules by defining (), with the same parameters defined.Methods and variables within this module are inaccessible outside the module and can only be return ed.

define module

define(['jquery'], function ($) {//Introducing jQuery modules
    return {
        add: function(x,y){
            return x + y;
        }
    };
});

Save the module named math.js.

main.js introduces module approach

require(['jquery','math'], function ($,math) {
    console.log(math.add(10,100));//110
});

No Dependency

If the defined module does not depend on other modules, you can:

define(function () {

    return {
        name: "trigkit4",
        age: "21"
    }
});

AMD's recommended style exposes module objects by returning an object as a module object and CommonJS's style exposes module objects by assigning attributes to module.exports or exports.

Posted by pmjm1 on Mon, 23 Mar 2020 10:53:05 -0700