This article brings you the content is about JavaScript modularization of the detailed introduction, there is a certain reference value, the need for friends can refer to, I hope to help you.
Objective
With the development of WEB technologies and the growing infrastructure that relies on it, the front-end domain is gradually expanding from browser to server (node. js), Desktop (PC, Android, IOS), and even Internet of Things (IoT), where JavaScript Bearing the core of these applications, as its scale and complexity multiply, its software engineering system is also built up (collaborative development, unit testing, demand and defect management, etc.), the need for modular programming is increasingly urgent.
JavaScript support for modular programming has not yet become a norm, it is difficult to do this task; For a time, the Lake Chevalier Stand up, all the way, from slash and burn transition to the future-oriented modular program;
<!--more--
Concept
Modular programming is the implementation of the function by combining some of the relatively independent reusable modules, the core of which is the definition of modules __ and __ The introduction of modules __;
When the module is defined, the execution logic inside each module is not externally sensed, only some methods and data are exported (exposed);
When the module is introduced, the code to be introduced is loaded synchronously/asynchronously, and the methods and data of its exposure are executed and obtained;
Slash
Although the JavaScript language level does not provide a modular solution, but the use of its object-oriented language features, plus the design mode __, can implement some simple modular architecture; A classic case is the use of a single pattern mode to achieve modularity, The module can be better encapsulated, only to expose some information to the need to use the module;
Define a Modulevar Modulea = (function ($, doc) { var MethodA = function () {}; var dataa = {}; return { Methoda:methoda, dataa:dataa };}) (JQuery, document);//Use a modulevar result = Modulea.mehoda ();
Intuitively, by executing functions immediately (Iife) to declare dependencies and to export data, there is no significant difference between the present modular scheme, but in essence, there are some important features that are different and cannot be satisfied.
When defining a module, the declared dependency is not forced to be introduced automatically, i.e. the dependent module code must be introduced manually before the module is defined;
When the module is defined, its code has completed the execution process, unable to implement on-demand loading;
When using a module across files, you need to mount the module to a global variable (window);
AMD & CMD Two-point world
Off-topic: Because of the age, these two modular schemes gradually fade out of the historical stage, the specific characteristics no longer chat;
To address the needs of the "slash and Burn" era, the AMD and CMD modular specifications have been introduced to address the need for asynchronous, modular programming on the browser side, and the core principle is to load modules asynchronously by dynamically loading script and event snooping; __
AMD and CMD are the most representative of the two works corresponding to Require.js and Sea.js, the main difference is the time to rely on the declaration and dependency loading, where require.js by default in the declaration, sea.js respected lazy loading and on-demand use, and also worth mentioning is that the CMD specification The writing and CommonJS are very similar, only a little modification, can be used in the CommonJS. Reference to the following case is more helpful to understand;
Amddefine (['./a ', './b '], function (Modulea, Moduleb) { //relies on the predecessor Modulea.mehoda (); Console.log (moduleb.datab); Export Data return {};}); Cmddefine (function (Requie, exports, module) { //dependent on the nearest var Modulea = require ('./a '); Modulea.mehoda (); Load on Demand if (Needmoduleb) { var Moduleb = Requie ('./b '); Moduleb.methodb (); } Export Data exports = {};});
CommonJS
2009 Ty released the first version of node. js, CommonJS as one of the core features of the service-side scenario, the review and Time of the year, and the full support of the front-end engineering, CommonJS is widely used in node. js and the browser;
Core moduleconst CP = require (' child_process ');//Npm Moduleconst Axios = require (' Axios ');//Custom moduleconst foo = Require ('./foo '); module.exports = {Axios};exports.foo = foo;
Specification
Module (Object): modules themselves
Exports (*): The exported part of the module, i.e. the exposed content
Require (function): Load module functions, get the exported value of the target module (base type is copy, reference type is shallow copy), can load built-in module, NPM module and custom module
Realize
1. Module definition
The default arbitrary. Node. js. json files are modules that conform to the specification;
2. Introduction module
The module is first read from the cache (Require.cache), and if the cache is not hit, the path is analyzed and then processed according to the different types of modules:
Built-in modules, loaded directly from memory;
External module, the first file addressing location, then compile and execute, and finally get the corresponding export values;
In the process of compiling, node wraps the contents of the obtained JavaScript files, and the result is as follows:
(function (exports, require, module, __filename, __dirname) { var circle = require ('./circle.js '); Console.log (' The area of a circle of radius 4 is ' + Circle.area (4));});
Feature summary
Synchronous execution of the module declaration and introduction of logic, analysis of some complex dependent references (such as cyclic dependencies) should be noted;
Caching mechanism, better performance, and limit the memory consumption;
Module module can be retrofitted with a high degree of flexibility to achieve a number of customization requirements (such as hot update, Arbitrary file type module support);
ES Module (recommended)
ES module is the language level of the modular scheme, proposed by ES 2015, its specifications and CommonJS ratio, the value of the exported <span data-type= "color" style= "Color:rgb (+,,,)" ><s Pan data-type= "Background" style= "Background-color:rgb (255, 255, 255)" > can be seen as an object with multiple properties or methods </span></ Span>, can be compatible with each other, but the syntax of the ES Module is more concise, close to Python;
Import FS from ' FS '; Import color from ' color '; Import service, {getarticles} from '. /service '; Export default Service;export Const Getarticles = getarticles;
The main difference is:
ES Module will be <span data-type= "color" style= "Color:rgb (+,-)" ><span data-type= "background" style= " Background-color:rgb (255, 255, 255) "> Static code Analysis, which is the loading of the module at compile time, has determined the dependencies before the runtime (which solves the problem of circular references); </span></ Span>
ES Module Keywords: import
export
as well as the unique default
keywords, determine the default export values;
<span data-type= "Color" style= "Color:rgb" ><span data-type= "Background" style= "Background-color: RGB (255, 255, 255) "The properties or methods of importing modules in the >es module are strongly bound, including the underlying type;</span></span>
Umd
Through a layer of self-executing function to be compatible with a variety of modular specifications, compatible with AMD/CMD/COMMONJS and other modular specifications, paste the code over thousands of words, need to pay special attention to the ES Module because of the static code analysis, so this run-time scenario can not be used, at this time through CommonJS for compatibility;
(function (global, factory) { if (typeof exports = = = ' object ') { module.exports = Factory (); } else if (typeof define = = = ' function ' && define.amd) { define (factory); } else { this.eventutil = Factory ()} ) (This, function (exports) { //Define Module object.defineproperty (exports, "__esmodule", { value:true }); Exports.default = 42;});
Implementation in the Build tool
In order to run the modular code in a browser environment, it needs to be packaged with some modular packaging tools (Webpack, for example), after the project portal is defined, the dependency analysis is performed quickly and then all dependent modules are converted to the implementation of the browser-compatible corresponding modular specification;
The basics of modularity
From the above introduction, we have a certain understanding of its specification and implementation, in the browser, to implement the CommonJS specification, only need to implement module/exports/require/global these properties, because the browser is unable to access the file system, so requ The file location in the IRE process needs to be modified to load the corresponding JS fragment (Webpack is adopted by the introduction of dependency through function parameters). Concrete implementation can refer to: Tiny-browser-require.
Webpack packaged code snapshots are as follows, pay attention to the timing in the comments;
(function (modules) { //the module cache var installedmodules = {}; The Require function function __webpack_require__ (moduleid) {} return __webpack_require__ (0);//---> 0}) ({ 0:function (module, exports, __webpack_require__) { //Define module A var moduleb = __webpack_require__ ( 1); ---> 1 }, 1:function (module, exports, __webpack_require__) { //Define module B exports = {};/// ---> 2 }});
In fact, the ES module handles the same as CommonJS, only when the module is defined and the module is introduced to handle the __esmodule identity, which is compatible with its grammatical differences.
Asynchronous and extended
1, the browser environment, network resources are subject to a large limit, so the packaging of the file if the volume is huge, the loss of the page performance is very large, so the construction of the target file needs to be split, while the module also needs to support dynamic loading;
Webpack provides two methods Require.ensure () and import () (recommended) for dynamic loading of modules, as to the principle of which, with the above mentioned AMD & CMD minded, import () executes after the return of a Promise object, The work done is nothing more than a dynamic new script tag, which is then processed further through the Onload/onerror event.
2, since the Require function is fully customizable, we can implement more features in modularity, such as CSS/. JSX/. Vue/Picture files by modifying the file types supported by the Require.resolve or module._extensions extension. can also be used for modularity;
Appendix: Features List
Modular Specification |
Load Mode |
Loading Time |
Operating Environment |
Notes |
Amd |
Asynchronous |
Run-time |
Browser |
|
Cmd |
Asynchronous |
Run-time |
Browser |
|
CommonJS |
Synchronous/Asynchronous |
Run-time |
Browser/Node |
|
ES Module |
Synchronous/Asynchronous |
Compile phase |
Browser/Node |
Asynchronous loading via import () |