持续补充中…
模块化是为了更高效地复用代码,减少重复代码,提高代码的可读性,可维护性,可复用性。
javascript 中的模块化有多种实现方式,本文主要介绍 CommonJS、AMD、CMD、ES6 模块化以及 UMD(通用模块定义)。
模块化分类
按端分类
- 服务端
CommonJS - 浏览器端
AMD、CMD、ES6 Module 
按同步异步分类
- 同步
CommonJS - 异步
AMD、CMD、ES6 Module 
按是否可以条件加载分类
- 可以条件加载
CommonJS、AMD、CMD - 不能条件加载
ES6 Module 
CommonJS(CJS)
CommonJS 是服务器端模块化的一种实现方式,最初是由 Node.js 团队实现的,它通过 require()和 exports()来实现模块的加载和使用。
特点
- 在服务端使用
 - 导出的模块为原始值的复制或深拷贝(重点)
 
代码
目录结构:
- main.js
 - module1.js
 - module2.js
 
1 2 3 4 5 6 7 8
   |  let name1 = "模块1"; function introduce1() {   console.log(`我是${name1}`); }
 
  module.exports = { name1, introduce1 }; 
 
  | 
1 2 3 4 5 6 7 8
   |  let name2 = "模块2"; function introduce2() {   console.log(`我是${name2}`); }
 
  module.exports = { name2, introduce2 }; 
 
  | 
1 2 3 4 5 6 7 8 9
   | 
  const { name1, introduce1 } = require("./module1.js");  console.log(name1); introduce1(); 
  const { name2, introduce2 } = require("./module2.js"); console.log(name2); introduce2(); 
 
  | 
AMD
AMD 是浏览器端模块化的一种实现方式,最早是由 RequireJS 团队实现的,它通过 define()和 require()来实现模块的加载和使用。
RequireJS 官网 
特点
- 不能按需加载(和 CMD 相比)
AMD 的依赖只要声明了就会被加载 
代码
目录结构:
- index.html
 - js
- main.js
 - require2.3.6.js
 - lib
 
 
1 2 3 4 5 6 7 8 9 10 11 12
   |  <!DOCTYPE html> <html lang="en">   <head>     <meta charset="UTF-8" />     <meta name="viewport" content="width=device-width, initial-scale=1.0" />     <title>Document</title>   </head>   <body>     <script src="js/require2.3.6.js" data-main="js/main"></script>   </body> </html>
 
  | 
1 2 3 4 5 6 7 8 9 10 11 12 13 14
   |  require.config({   baseUrl: "js/lib",             });
  require(["module1"], function (module1) {   console.log(module1.name1);   module1.introduce1();   module1.myFriend(); });
 
  | 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
   |  define(["module2"], function (module2) {   let name1 = "模块1";   function introduce1() {     console.log(`我是${name1}`);   }   function myFriend() {     console.log(`我是${name1},我的朋友是${module2.name2}`);   }   return {     name1,     introduce1,     myFriend,   }; });
 
  | 
1 2 3 4 5 6 7 8 9 10 11
   |  define(function () {   let name2 = "模块2";   function introduce2() {     console.log(`我是${name2}`);   }   return {     name2,     introduce2,   }; });
 
  | 
CMD
CMD 是浏览器端模块化的一种实现方式,最早是由 SeaJS 团队实现的,它通过 define()和 require()来实现模块的加载和使用。
SeaJS 官网 
特点
- 可以按需加载(和 AMD 相比)
CMD 的依赖仅在需要使用时主动声明才会被加载 
代码
目录结构:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
   |  <!DOCTYPE html> <html lang="en">   <head>     <meta charset="UTF-8" />     <meta name="viewport" content="width=device-width, initial-scale=1.0" />     <title>Document</title>   </head>
    <body>     <script src="js/sea.js"></script>     <script>              seajs.config({         base: "./js/lib",                                           });
               seajs.use("./js/main");     </script>   </body> </html>
 
  | 
1 2 3 4 5 6 7
   |  define(function (require, exports, module) {   let module1 = require("module1");   console.log(module1.name1);   module1.introduce1();   module1.myFriend(); });
 
  | 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
   |  define(function (require, exports, module) {   let name1 = "模块1";   function introduce1() {     console.log(`我是${name1}`);   }   var module2 = require("module2");   function myFriend() {     console.log(`我是${name1},我的朋友是${module2.name2}`);   }   module.exports = {     name1,     introduce1,     myFriend,   }; });
 
  | 
1 2 3 4 5 6 7 8 9 10 11
   |  define(function (require, exports, module) {   let name2 = "模块2";   function introduce2() {     console.log(`我是${name2}`);   }   module.exports = {     name2,     introduce2,   }; });
 
  | 
ES6 Module(ESM)
ES6 Module 是浏览器端模块化的一种实现方式,是在语言层面上的实现的模块化标准,它通过 import 和 export 来实现模块的加载和使用。
特点
- 不能条件加载
ES6 的模块不是对象,import 命令会被 JavaScript 引擎静态分析,在编译时就引入模块代码,而不是在代码运行时加载,所以无法实现条件加载。也正因为这个,使得静态分析成为可能。 - 兼容性问题
目前谷歌浏览器已原生支持 ESM,但是考虑到不同用户的浏览器版本参差不齐,所以兼容性还是要考虑的首要问题 - 需要服务器环境
通过文件协议访问网页不能使用 ESM 
代码
目录结构:
- public
- index.html
 - main.js
 - module1.js
 - module2.js
 
 - node_modules
- http-server:因为 ESM 需要部署在服务器,所以使用该第三方库来开启服务
 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
   |  <!DOCTYPE html> <html lang="en">   <head>     <meta charset="UTF-8" />     <meta name="viewport" content="width=device-width, initial-scale=1.0" />     <title>Document</title>   </head>
    <body>          <script type="module">       import "./main.js";      </script>   </body> </html>
 
  | 
1 2 3 4 5 6 7 8 9
   |  import { name1 as newName, introduce1 } from "./module1.js";  import module2 from "./module2.js"; 
  console.log(newName); introduce1();
  console.log(module2.name2); module2.introduce2();
 
  | 
1 2 3 4 5 6 7
   |  export let name1 = "模块1"; 
 
  export function introduce1() {   console.log(`我是${name1}`); }
 
  | 
1 2 3 4 5 6 7 8 9 10 11
   |  let name2 = "模块2"; function introduce2() {   console.log(`我是${name2}`); }
 
  export default {   name2,   introduce2, };
 
  | 
UMD
UMD(Universal Module Definition)并非是一个实现模块化的第三方库,
它只是一种用来编写 javascrit 库的通用模式,该模式会自动判断当前环境应该使用什么模块化标准,
比如 JQuery 就使用了 UMD 模式,所以它在 CommonJS、AMD、CMD、ES6 Module 模块化标准中都可以使用
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
   | 
 
 
 
 
 
  (function (root, factory) {   if (typeof define === "function" && define.amd) {          define(["exports"], factory);   } else if (typeof exports === "object") {          module.exports = factory();   } else {          root.MyModule = factory();   } })(this, function () {      var MyModule = {};
    MyModule.someFunction = function () {        };
    return MyModule; });
 
  | 
参考