historical background
JS itself simple page design: page animation + form submission
There is no modular or namespace concept
With the increasing complexity of front-end pages, the previous methods can not meet the requirements
Therefore, JS has an increasing demand for modularity
development history
Infancy: no modularization
- Pages need js with different functions - animation, form, formatting
- Various js files are divided into different files
- Different files are referenced by the same template
<script src="jquery.js"></script> <script src="main.js"></script> <script src="dep1.js"></script>
Advantages: File separation can play the role of module reuse and better maintenance.
Disadvantages: it will pollute the global scope = > it is not conducive to the development of large projects and the cooperation of multi person teams.
Growth: prototype of modularization - IIFE (optimization of syntax side)
It mainly increases the control of the scope
example:
// Common practice - pollution global scope let count = 0; const increase = () => ++count; const reset = () => { count = 0; } increase(); reset(); // Utilizing IIFE const iifeModule = (() => { let count = 0; return { increase: () => ++count, reset: () => { count = 0 } } })(); iifeModule.increase(); iifeModule.reset(); // Optimize IIFE above - inject other dependencies const iifeModule = ((dependencyModule1, dependencyModule2) => { let count = 0; return { increase: () => ++count, reset: () => { count = 0 } } })(dependencyModule1, dependencyModule2); iifeModule.increase(); iifeModule.reset(); // Imitate the dependency processing and module loading of early jquery const iifeModule = ((dependencyModule1, dependencyModule2) => { let count = 0; const increase = () => ++count; const reset = () => { count = 0; } // In fact, the disclosure mode is used return { increase, reset } })(dependencyModule1, dependencyModule2); iifeModule.increase(); iifeModule.reset();
Maturity: CJS - CommonJs
By node JS development
features:
- Expose the interface through module + exports
- Call other modules through require
Module organization
// main.js file const dependencyModule1 = require('./dependencyModule1'); const dependencyModule2 = require('./dependencyModule2'); // Treatment method let count = 0; const increase = () => ++count; const reset = () => { count = 0; } // Do something related to introducing dependencies // Exposed interface // 1 exports.increase = increase; exports.reset = reset; // 2 module.exports = { increase,reset }
Module usage
const { increase, reset } = require('./main.js'); increase(); reset();
Actual execution processing - bottom layer
(function(thisValue, exports, require, module) { const dependencyModule1 = require('./dependencyModule1'); const dependencyModule2 = require('./dependencyModule2'); // Business logic }).call(thisValue, exports, require, module)
- Advantages: CommonJs is the first to be implemented on the server side, and solves the problems of dependency and global variable pollution from the framework level
- Disadvantages: it mainly aims at the solution of the server, and is not so friendly to the processing and integration of asynchronous pull dependency
AMD specification
Allow the formulation of callback functions through asynchronous loading (classic implementation framework: require.js)
New definition method:
// Define a module through define, and then load it with require /* * define * params: Module name, dependent module, factory method **/ define(id, [depends], callback); require([module], callback);
Module definition method:
define('amdModule', [dependencyModule1, dependencyModule2], (dependencyModule1, dependencyModule2) => { // Business logic // processing section let count = 0; const increase = () => ++count; const reset = () => { count = 0; } return { increase, reset } })
Lead in module:
require(['amdModule'], amdModule => { amdModule.increase(); })
Existing code compatible with CMJ in ADMmodule
define('amdModule', [], require => { // Introduction part const dependencyModule1 = require(./dependencyModule1); const dependencyModule2 = require(./dependencyModule2); // processing section let count = 0; const increase = () => ++count; const reset = () => { count = 0; } // Do something related to introducing dependencies return { increase, reset } })
Using revealing in AMD
define('amdModule', [], (require, export, module) => { // Introduction part const dependencyModule1 = require(./dependencyModule1); const dependencyModule2 = require(./dependencyModule2); // processing section let count = 0; const increase = () => ++count; const reset = () => { count = 0; } // Do something related to introducing dependencies export.increase = increase(); export.reset = reset(); }) define('amdModule', [], require => { const otherModule = require('amdModule'); otherModule.increase(); otherModule.reset(); })
Compatible with AMD & CMJ / how to judge CJS and AMD
Emergence of UMD
(define('amdModule', [], (require, export, module) => { // Introduction part const dependencyModule1 = require(./dependencyModule1); const dependencyModule2 = require(./dependencyModule2); // processing section let count = 0; const increase = () => ++count; const reset = () => { count = 0; } // Do something related to introducing dependencies export.increase = increase(); export.reset = reset(); }))( // The goal is to differentiate CommonJSorAMD at one time typeof module === "object" && module.exports && typeof define !== "function" ? // It's CJS factory => module.exports = factory(require, exports, module) : // It's AMD define )
- Advantages: it is suitable for loading asynchronous modules in the browser, and multiple modules can be loaded in parallel
- Disadvantages: there will be an introduction cost, and it cannot be loaded on demand
CMD specification
Load the main application framework sea js
define('module', (require, exports, module) => { let $ = require('jquery'); // jquery related logic let dependencyModule1 = require('./dependecyModule1'); // dependencyModule1 related logic })
- Advantages: load on demand and rely on nearby
- Disadvantages: depending on packaging, the loading logic exists in each module and expands the volume of the module
ES6 modularization
New definition:
import Keyword - import
Export Keyword - export
// Introduction area import dependencyModule1 from './dependencyModule1.js' import dependencyModule2 from './dependencyModule2.js' // Implement code logic let count = 0; export const increase = () => ++count; export const reset = () => { count = 0; } // Export area export default { increase,reset } // Module introduction <script type="module" src="esModule.js"></script>
Dynamic module - Inspection: export promise
ES11 native solution:
import('./esModule.js').then(dynamicEsModule => { dynamicEsModule.increase(); })
- Advantages (importance): it integrates js modules in the most unified form
- Disadvantages (limitations): it is essentially runtime dependency analysis
(important) a new idea to solve modularization - front end Engineering
background
Fundamental problem - the modular approach of the front end depends on runtime analysis
Solution - offline execution: gulp webpack
<!doctype html> <script src="main.js"></script> <script> // Give the build tool an identification bit require.config(__FRAME_CONFIG__); </script> <script> require(['a', 'e'], () => { // Business processing }) </script> </html>
define('a', () => { let b = require('b'); let c = require('c'); export.run = () { // run } })
Engineering realization
step1: scan dependency table
{ a: ['b', 'c'], b: ['d'], e: [] }
Step 2: regenerate the dependent data template
<!doctype html> <script src="main.js"></script> <script> // Build tool generates data require.config({ "deps": { a: ['b', 'c'], b: ['d'], e: [] } }) </script> <script> require(['a', 'e'], () => { // Business processing }) </script> </html>
step3: an execution tool, which adopts a modular solution to solve the modular processing dependency
define('a', ['b', 'c'], () => { // Execute code export.run = () => {} })
- advantage:
- The configuration is generated at build time and executed at run time
- Finally, it is transformed into execution processing dependency
- Can expand