Recently, I was sorting out some knowledge points, and I was trying to write an article in the process of reviewing. If there is a misunderstanding, thank the gods can point out.Copy the code

The origin of modularity

We all know that pages are made up of HTML, CSS, and JavaScript. As the functions of the page become more powerful, the page logic becomes more and more complex. JavaScript code inevitably becomes bloated. One of the earliest ways to split JS code is to split JS into different files and import them via the Scritpt tag. When we use a tool like jquery, if we use script reference friends can see that its JS is actually an IIFE. Internal contains the contents of the entire tool library, using IIFE to prevent contamination of the global part of the code, while passing in the window, the tool instance mount to the Window.

The problem with using too many tools is that dependencies like those tools can’t be controlled. So we need a new way to manage, and modularity seems to be the best way to manage any large project, so how does the front end achieve modularity?

AMD (Asynchromous Module Definition) specification

The emergence of require.js provides a modular idea and forms what we call the AMD specification.

The overall plan is as follows: 1. When we write a module, we need to have a “define” step. Every time we define our module through the define function, the define function takes three parameters.

  • The first argument is the name of the module;
  • The second argument is an array that declares the module’s dependencies.
  • The third argument is a function whose arguments correspond to the dependencies of the second argument. The function provides a private space for the current module.

Example:

define('myModule'['jquery'.'lodash'].function($, _){
		return {
      // Jq can be referenced with $, regardless of the order in which the dependencies are referenced.
      getInputValue:function(){
      	var input = $('#input');
        returninput.val(); }}})Copy the code

More information can be found on require.js’s website: requirejs.org/

commonJS

CommonJs is believed to be the most familiar modular approach to any front-end, and it is nodeJs’ default modular approach. One of the most important things nodeJs has done since its emergence as a server-side language, besides allowing front-end developers to move out of the browser, is to bring a truly “official” approach to modularity that makes front-end engineering a reality.

In a nodeJs environment, each file is a module. Modules are referenced between modules via require, and modules themselves are exported using module.exports. NodeJs modules are all loaded together at startup rather than during execution, which is a bit different from a browser.

Example:

// a.js
var printSolgan = function(){
	console.log('hello world');
}
module.exports = printSolgan;
//b.js
var printSolgan =  require('./a.js');
printSolgan();
// hello world
Copy the code

CMD (Common Module Definition) specification

CMD is an optimization for AMD, and after the commonJs specification came out, front-end developers had to remember two different references (browser, and nodeJs environment). It would be a great help to front-end developers if they could make the same script compatible with both environments. CMD is the answer to the problem, which was first realized by the front end team of Taobao launched sea-.js, and then require.js integrated it. He took the commonJs script and put it in the browser.

Example:

define(function(require.exports.module){
  var$=require('jqurey');
 	var getInputValue = function(){
      	var input = $('#input');
        return input.val();
      }
  module.exports = getInputValue;
})
Copy the code

It can be seen that CMD implements the native content of NodeJS, such as require, module, etc. Of course, the module definition still needs to call define function, which is very similar to the nodeJS environment.

More content available sea. Js document: seajs. Making. IO/seajs/docs

ES Modules

ES modular approach is another official modular approach that was dropped after ES 2015, and it is the most used approach now. ES modules are often written in Babel or typescript compilations in nodeJs environments.

Example:

// a.js
var printSolgan = function(){
	console.log('hello world');
}
export default printSolgan;

//b.js
import printSolgan from './a.js';
printSolgan();
// hello world
Copy the code

You can see that ES Module uses a different alias to import and export modules. Note that when using es module in the browser, you need to add ‘type=”module” to the script tag.

   <script type="module">
        var foo = 100;
        console.log(foo);/ / 100
    </script>
Copy the code

Module type compatibility

As can be seen from the above content, the development of front-end modularization has experienced a very long process. Different developers may exist in different environments. So if we develop a tool library, can it be compatible with different module solutions? The answer can be found in jqurey’s source code.

Jquery 3.6 CDN address: cdn.bootcdn.net/ajax/libs/j…

Jq as a whole is a self-executing function that forms a closure. Enter two parameters.

  • G is to check whether there is a window globally and whether it is running in the front end.
  • Check whether it is running in a browser or nodeJS by checking whether there are Windows and global.
  • The outer layer checks whether commonJS is supported or not. If it is supported, make sure that document is in global and factory is in global.
  • If not, the factory operation is supported.
var g = typeof window! = ="undefined" ? window : this;
// g is used to check whether there is a global window or whether it is running in the front end.
(function (global, factory) {
    // Browser (webView & webpack):global-->window
    // NODE environment :global-->global/ module
    "use strict";
    if (typeof module= = ="object" && typeof module.exports === "object") {
        // The current environment supports the CommonJS specification: NODE & Webpack
        module.exports = global.document ?
            // global-->window indicates that it is running in webpack environment
            factory(global.true) :
            JQ does not support running in NODE
            function (w) {
                if(! w.document) {throw new Error("jQuery requires a window with a document");
                }
                return factory(w);
            };
    } else {
        // Browser (webview)
        factory(global);
    }
})(g, factory);
Copy the code

The factory function is mainly for module compatibility

  • Come in from above. In addition to global, there is a judgment noGlobal. Because there must be Windows to get in. So the main function of noGlobal is to determine if it is a Webpack
  • The noConflict function operates window. The current is logged at jQ initialization. The current is logged at jQ initialization. The current is logged at jQ initialization. If noConfilt is used, the $is returned and jQ is returned for the user to define in the variable.
  • Amd compatible, is to see whether there is no define and define. Amd
  • It is compatible with direct SRC references in HTML, since there is no import in this way so that users can operate on their own. So you need to be exposed to the big picture.
  • Compatible with CommonJS, since CMD comes in from above, just return can be used.
var factory = function factory(window, noGlobal) {
    // webpack : window-->window noGlobal-->true
    // browser (webview): window-->window noGlobal-->undefined
    "use strict";
    var version = "3.6.0",
        jQuery = function (selector, context) {
            return new jQuery.fn.init(selector, context);
        };
    / /...

    //===================== conflict handling
    / / the scene
    // 
    // window.$=Zepto;
    // 
    // var _$=window.$; // _$===Zepto
    // jQuery.noConflict = function (deep) {}
    // 
    // window.$=jQuery;
    $.noconflict () let jj=$.noconflict (
    var _jQuery = window.jQuery,
        _$ = window. $; jQuery.noConflict =function (deep) {
        if (window.$ === jQuery) {
            window. $= _ $; }if (deep && window.jQuery === jQuery) {
            window.jQuery = _jQuery;
        }
        return jQuery;
    };

    / / = = = = = = = = = = = = = = = = = = = = = export API
    // Make it support the AMD module specification
    if (typeof define === "function" && define.amd) {
        define("jquery"[],function () {
            return jQuery;
        });
    }
    / / if directly in the browser (webview) based on < script SRC = 'jquery. Js' > import JQ, we exposed in the global object "jquery | $"
    if (typeof noGlobal === "undefined") {
        window.jQuery = window.$ = jQuery;
    }
    Module. exports=jQuery, CommonJS specification supported
    return jQuery;
};
Copy the code

If you get something, give it a thumbs up