Modularity Background

Early Javascript programs were small and mostly used to perform stand-alone scripting tasks, providing some level of interaction. There are now complex programs that run a lot of Javascript scripts, and some that are used in other environments (such as Node.js). Therefore, it is necessary to start thinking about providing a mechanism for breaking uP JavaScript programs into separate modules that can be imported on demand.

Modules in Javascript need to solve the problem of how to encapsulate a piece of code into a useful unit, how to register its functions/export values for the module, and how to reference other code units.

Babel module related plug-in

  • babel-plugin-transform-modules-amd
  • babel-plugin-transform-modules-commonjs
  • babel-plugin-transform-modules-umd

The traditional method

In the case of Jquery, how were snippets defined previously?

/ / Jquery examples
(function(window.undefined){
    window$=window.JQuery;
    var JQuery = function(selector){}}) (window)
Copy the code
  • Defined by immediate Function Call expression (IIFE)
  • References to dependencies are done by global variable names loaded through HTML script tags.
  • The description of dependencies is very weak: the developer needs to know the correct order of dependencies. For example, the file containing Backbone cannot precede the jQuery tag.
  • It requires additional tools to replace a set of script tags with a single tag to optimize deployment.
  • On large projects, this can be difficult to manage, especially when scripts start to have many dependencies in ways that may overlap and nest. Handwritten script tags are not very scalable, so scripts cannot be loaded on demand.

CommonJS

CommonJS, formerly known as ServerJS, is the JS specification on the server that Node uses. According to the CommonJS specification, a single file is a module, require is used to load a module, exports is used to expose methods or properties in that module to the outside world, and load modules are synchronous.

CommonJS specification

AMD (Asynchronous Module Definition)

The AMD specification lays down rules for defining modules so that modules and module dependencies can be loaded asynchronously. This is appropriate for an environment where browsers load modules asynchronously (which can cause performance, availability, debugging, and cross-domain access issues).

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

define(id? , dependencies? , factory);Copy the code

Id is the name of a module, dependencies is an array of dependencies, and the factory method factory initializes functions or objects to be executed by the module

  • Register the factory function by calling define() rather than executing it immediately.
  • Pass dependencies as arrays of string values, not global variables.
  • The factory function is executed only after all dependencies are loaded and executed.
  • Pass the relevant module as an argument to the factory function.
// The global function define should implement binding amd attributes to prevent conflicts with existing code that defines define functions but does not comply with AMD programming interfaces
define.amd = {};

// Check whether the current page has AMD module loader
if (typeof define === "function" && define.amd) {
    // ...
}
Copy the code

requirejs

RequireJS is based on the AMD module loading specification and uses callback functions to solve module loading problems.

RequireJS loads modules by creating script elements and specifying the SRC attribute of the script element.

CMD (Common Module Definition)

In the CMD specification, a module is a file

define('hello'['jquery'].function(require.exports.module) {
// require
  // require is a method that takes a module identity as a unique argument to get interfaces provided by other modules
  The require.async method is used to load the module asynchronously inside the module and execute the specified callback when the load is complete. The callback parameter is optional
  Resolve resolves and returns the module path using the module system's internal path resolution mechanism. This function does not load the module and only returns the absolute parsed path
// exports
  // Exports is an object that provides module interfaces
  // You can also use return to provide the interface directly
  // exports is just a reference to module.exports. Module. exports does not change its value when reassigning exports inside the factory. So assignments to exports are not valid and cannot be used to change module interfaces
//module
  // Module is an object that stores properties and methods associated with the current module
  // module.uri String Indicates the absolute path of the module obtained according to the path resolution rules of the module system
  // module.dependencies is an array representing the dependencies of the current module
  // module.exports Specifies the interface provided by the current module
  // module.exports assignments need to be executed synchronously and cannot be placed in callbacks
});

// Check whether the current page has a CMD module loader
if (typeof define === "function" && define.cmd) {
}
Copy the code

seajs

SeaJS is a module loader that follows the CMD specification.

UMD (Universal Module Definition)

UMD provides a common schema that supports multiple styles and is compatible with CommonJS and AMD specifications while also being compatible with the global reference approach

// babel UT output code

(function (global, factory) {
  if (typeof define === "function" && define.amd) {
    // Check whether AMD is supported
    define(["exports"], factory);
  } else if (typeof exports! = ="undefined") {
    // No Node.js module format is supported
    factory(exports);
  } else {
    var mod = {
      exports: {}}; factory(mod.exports);global.input = mod.exports;
  }
})(typeofglobalThis ! = ="undefined" ? globalThis : typeofself ! = ="undefined" ? self : this.function (_exports) {
  "use strict";

  Object.defineProperty(_exports, "__esModule", {
    value: true
  });
  _exports.default = void 0;
  var _default = {};
  _exports.default = _default;
});
Copy the code

ES6 module

  • ES6 modules are loaded at compile time through static analysis
  • UMD module format is not required, ES6 module format will be supported by servers and browsers in the future.
  • In the future, the browser’s new apis can be provided in module format and no longer have to be global variables or properties of navigator objects.
  • Instead of requiring objects as namespaces (such as Math objects), these capabilities can be provided through modules in the future.

ES6 module

Browser support module

The latest browsers are starting to support modules natively, allowing browsers to optimally load modules more efficiently than using libraries: libraries often require additional client-side processing.

  • HTML USEStype="module"The script tag
  • Native JavaScript modules, used.mjsExtension,MIME-typejavascript/esmThe import file
    • It’s pretty clear, which files are modules and which are regular JavaScript.
    • This ensures that your modules are recognized by the runtime environment and build tools, such as Node.js and Babel
  • The syntax of export import is the same as ES6
  • The path of the import module file is relative to the root directory of the site, or the current path is denoted by dot syntax
  • Loading Html files locally (such as a file:// path file) causes CORS errors because Javascript module security needs to be tested by a server.
  • The module automatically adopts strict mode, regardless of whether you add “Use strict” to the module header.
  • You don’t need to use the defer attribute to load a module script; the module automatically loads lazily.

Dynamic loading module

Call import() as a function, returning a Promise with a module object as a parameter

import('/modules/myModule.mjs')
  .then((module) = > {
    // Do something with the module.
  });
Copy the code

reference

Webpack module

Webpack modules can express their dependencies in a variety of ways, several examples of which are as follows:

  • ES2015 import statements
  • CommonJS require () statement
  • AMD DEFINE and require statements
  • @import statement in CSS /sass/ LESS files.
  • Style (url (…). ) or HTML file (<img src=... >Image url in)