# Front-end modular history

1. Why modularity

  • 1. Remove common code
  • 2. Isolate scopes to avoid variable conflicts

2. Front-end development history

  • “Age
    • The web page is “read-only”, so users can only search for information and browse information.
  • Web2.0 era
    • The main feature is the concept of interaction, not just browsing, but creating and uploading content yourself
    • JavaScript was born as an embedded scripting language
  • The problems of Web2.0 + Ajax technology has been widely used, jQuery and other front-end libraries emerge in endlessly, and front-end code is expanding day by day, so the concept of modularity needs to be introduced in the front-end

3. Evolution of solutions

In response to these problems, front-end developers are beginning to explore their own solutions

  • IIFE

    So let’s start with a function for each function; Like this

    function fn1(){
       statement
    }
    
    function fn2(){
       statement
    }
    
    Copy the code

    The disadvantages of this approach are obvious: the contamination of global variables, there is no guarantee against variable name conflicts with other modules, and there is no relationship between module members. In order to solve the above problems, object writing method came into being, you can encapsulate all module members in one object like this

      var myModule = {
          var1: 1,
      
          var2: 2,
      
          fn1: function(){
      
          },
      
          fn2: function(){
      
          }
      }
    Copy the code

    This may seem like a good solution, but it has its drawbacks: outsiders can modify internal members at will; For example, myModule.var1 = 100; That creates a security problem so IIFE came up with IIFE: Immediately Invoked Function Expression, which means the Function Expression Invoked Immediately, that is, the Function Invoked Immediately as the Function was declared.

    var myModule = (function module(){ var someThing = "123"; Var otherThing = [1, 2, 3]; function doSomeThing(){ console.log(someThing); } function doOtherThing(){ console.log(otherThing); } return { doSomeThing:doSomeThing, doOtherThing:doOtherThing } })(); myModule.doSomeThing(); myModule.doOtherThing();Copy the code
  • Common.js was initially thought to be a bit of a dud, and the official API was only for browser-based applications. The CommonJS API filled the gap by defining many common applications (mainly non-browser applications) that use the API. Its ultimate goal is to provide a standard library similar to Python, Ruby and Java. That way, developers can use the CommonJS API to write applications that can then run in different JavaScript interpreters and different host environments. Node.js is a project developed using common.js and was born in 2009. In the browser environment, the lack of modules is not particularly problematic because web applications are of limited complexity; But on the server side, you have to have modules that interact with the operating system and other applications, or you can’t program at all. NodeJS is an implementation of the CommonJS specification. What is the simplest common.js module reference to see how common.js works

    A.js
    function speak(name){
    console.log('speak name')
    }
    module.exports = speak
    
    B.js
    require('./A.js')
    speak('common.js')
    // common.js
    Copy the code

    Let’s write a common.js specification

    (function (exports, require, module, __filename, __dirname) { module.exports = function () { console.log(__dirname); }})Copy the code

    All Node does is call this method, passing in exports, require, module, __filename, __dirname

    I googled the require method

    const fs = require('fs'); const path = require('path'); const vm = require('vm'); // Virtual machine, Const wrapper = ['(function(exports, module, require){', '})'] function module (absPath) {this.id = absPath; // store current path this.exports = {}; } Module.prototype.load = function() { let script = fs.readFileSync(this.id, 'utf8'); let fnStr = wrapper[0] + script + wrapper[1]; let fn = vm.runInThisContext(fnStr); // The sandbox executes the current function fn(this.exports, this, req); } function req(file) {let absPath = path.resolve(__dirname, file); Let Module = new Module(absPath); // 2. Create a module module.load(); // exports; // exports. } let a = req('./a.js')Copy the code
  • A closer look at the code above will show 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 files need to be loaded to the browser earlier than the dependent files
    • 2. When js is loaded, the browser will stop page rendering. The more files loaded, the longer the page will lose response time
    Mymodule.js define(['dependency'], function(){var name = 'Byron'; function printName(){ console.log(name); } return { printName: printName }; }); // require(['myModule'], function (my){my.printName(); });Copy the code
  • CMD specification

    • 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, There are just differences in how modules are defined and when modules are loaded (run, parse, so to speak)

    • Syntax: Sea-.js advocates one file per module, following a uniform writing method

    • define(id? , deps? , factory)

    • Because CMD advocates

      A module is a file, so the file name is usually used as the module ID. CMD advocates the dependency nearby, so it is generally not written in the define parameter. Function (require, exports, module) require require is the first argument to factory

      Require (ID) require is a method that takes a module id as a unique argument and is used to obtain interfaces provided by other modules

      Exports Exports is an object that provides a module interface

      Module A module is an object that stores properties and methods associated with the current module

      // define mymodule. js define(function(require, exports,) module) { var $ = require('jquery.js') $('div').addClass('active'); }); / / load module seajs. Use ([' myModule. Js], function (my) {});Copy the code

    Yu Bo is the founder of KISSY, SeaJS, and Arale

    www.cnblogs.com/wpbars/p/42… The interview with Sea.js is recommended to solve many people’s confusion about native javascript and working with frameworks

    Q: Some argue that too much use of frameworks causes developers to neglect learning about JavaScript’s native language features, become lazy, or have a weak foundation; What do you think of the argument that you can develop an application without using a framework if you are proficient in native JavaScript?

    Yubo: The use of JavaScript is a relatively small part of the front-end development effort. More energy needs to be spent outside the language. To master the basic use of JavaScript language, just as we learn in school, we need to master the content of middle school mathematics. I think this is not difficult, as long as you take the time to learn. It’s worth noting that if you’re proficient in native JavaScript, it’s like learning math. While you can solve a lot of problems, it’s harder to solve them gracefully and simply. Frameworks can free you from repetitive low-level work, especially if the application is complex enough that without the abstraction of the framework layer, the code is often too complex to maintain. In today’s world of increasingly complex front-end development, frameworks are essential. Learn to use, to embrace, can get twice the result with half the effort. Frameworks don’t make you lazy, and they don’t make you weak. Even with jQuery, it’s hard to really use jQuery well if you don’t know the basic native manipulation of the DOM. It is just a dream to be good at college mathematics if you do not understand it in middle school.

  • 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

    AMD advocates dependency preloading. CMD advocates nearby dependency when defining a module, and requires only when a module is used. This distinction has its advantages and disadvantages, but there is a gap in syntax

  • UMD: Universal Module Definition (UMD) is a community approach that combines the CommonJS and AMD Module Definition specifications. The idea is to unify the different module definition specifications with a single factory function. Here is vUE 2.6 source code compiled using UMD

    / *! * Vue.js v2.6.10 * (c) 2014-2019 Evan You * Released Under the MIT License. */ (function (global, factory) { typeof exports === 'object' && typeof module ! == 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global = global || self, global.Vue = factory()); }(this, function () {// source content})Copy the code
  • The ES6 modularization specification ECMAScript 6 (ES6 for short) is a standard for the JavaScript language, officially named ECMAScript 2015, which was released in June 2015. Its goal is to make the JavaScript language usable for writing complex, large-scale applications as an enterprise-level development language.

       export const age = 12;
       export function play(){}
    
       import {age,play} from 'index.js'
    Copy the code
    The CommonJS module outputs a copy of the value, meaning that once a value is output, changes within the module do not affect that value. ES6 Modules don't work the same way as CommonJS. When the JS engine statically analyzes a script, it generates a read-only reference to the module load command import. When the script is actually executed, it will be evaluated in the loaded module based on the read-only reference. In other words, the IMPORT of ES6 is a bit like the "symbolic link" of Unix systems, where the original value changes and the import load value changes with it. Therefore, ES6 modules are referenced dynamically and do not cache values. Variables in modules are bound to the module in which they are located. (shallow copy) Runtime loading: CommonJS modules are objects; That is, the entire module is loaded on input, an object is generated, and methods are read from that object. This loading is called "runtime loading." Compile-time loading: ES6 modules are not objects, but are output code explicitly specified through the export command and static commands when importing. That is, when you import, you can specify that an output value is loaded, rather than the entire module, which is called "compile-time loading."Copy the code

4. How did the project we wrote in ES6 compile into a package for the AMD UMD CMD specification?

1. Most of the packaging tools on the market rely on Node. js, also known as common.js specification 2. 3. Each build tool is actually a project. The main job is to first identify es6 code such as let const class, and then translate the corresponding syntax into native javaScript. Modularized output through the configuration of the output module specification

Export = {output:{libraryTarget:'umd'}} // rollup.js output: [ { file: './lib/index.umd.js', name: 'NRTCCalling', format: 'umd', plugins: [!isDev && terser()], globals, }, { file: './lib/index.esm.js', format: 'esm', plugins: [!isDev && terser()], globals, }, { file: './lib/index.cjs.js', format: 'cjs', plugins: [!isDev && terser()], globals, }, ], ```Copy the code