# 模块化

# 发展历程

工具 时间
Node.js (CommonJS) 2009年
NPM 2010年
requireJS (AMD) 2010年
seaJS (CMD) 2011年
broswerify 2011年
webpack 2012年
grunt 2012年
gulp 2013年
react 2013年
vue 2014年
angular 2016年
redux 2015年
vite 2020年
snowpack 2020年

# 1. 刀耕火种的时代

// index.html 
<script src="./a.js"></script>   
<script src="./b.js"></script>   
<script src="./c.js"></script>   
<script src="./d.js"></script> 

//匿名闭包
<script>
  (function() {
    // ...
  })();
</script>
// 全局变量导入, 类似jquery
<script>
  (function ($, YAHOO) {
      // now have access to globals jQuery (as $) and YAHOO in this code
  }(jQuery, YAHOO));
</script>
// 模块导出
<script>
  var module2 = (function(){
   var a = module1.a;   
   return { b: a };
 })();
</script> 

这种方式存在问题:

  • 大量的script标签
  • 不能解决模块间的依赖关系
  • 同步加载的问题,导致页面卡死
  • 污染全局变量,导致命名冲突

# 2. node(CommonJS)

模块化的区别

# 3. (浏览器)进行时阶段

node的模块化让其名声大噪,人们开始思考浏览器的模块化
2010年出现AMD规范
2011年出现CMD规范

AMD

浏览器端的模块,不能采用"同步加载"(synchronous),只能采用"异步加载"(asynchronous)。这就是AMD规范诞生的背景。

两个api:defined和require

/**
 * @function 定义模块 
 * @params{1} array 依赖的模块名称
 * @params{2} function 这个方法通过入参的方式将所依赖模块的输出依次取出,并在方法内使用,同时将返回值传递给依赖它的其他模块使用
 */
define(['Module1', 'Module2'], function (module1, module2) {
    var result1 = module1.exec();
    var result2 = module2.exec();
    return {
      result1: result1,
      result2: result2
    }
}); 

/**
 * @function 引用模块 
 * @params{1} array 引用的模块名称
 * @params{2} callback 回调
 */
require(['Module1'], function (Module1) {
  Module1.result1(2, 3);
});

真棒! 刀耕火种时期的问题全部得到解决

  • 就近原则
  • 懒惰原则

关于以上原则,玉伯有自己的看法,于是,他提出了sea.js(CMD)

CMD

定义➡️

define(function(require, exports, module) {

  // The module code goes here
  // 通过 require 引入依赖
  var $ = require('jquery');
  var Spinning = require('./spinning');

  // 通过 exports 对外提供接口
  exports.doSomething = ...

  // 或者通过 module.exports 提供整个接口
  module.exports = ...
});

玉伯当年非常有意思的讨论:
前端模块化开发那点历史

# ES6 Modlue

模块化的区别

# 面试题

面试题中经常会说模块化的区别

  • AMD vs CMD:思想和追求上的差别
  • CommonJS vs ES6 module:值的输出方式的差别
  • CommonJS是服务端的,同步的;其他是浏览器端的,异步的; ES6 module是语言本身实现的

# 感悟

  • 虽然说CommonJS 、AMD、CMD、ES6 module的实现方式非常相似,但是规范的不同,导致每种方式的内部逻辑、生态、追求、核心思想都相差甚大。
  • 每个思想和技术的出现都是为了解决当时技术上的痛点,从实际触发~

# 参考资料

sea.js: https://github.com/seajs/seajs/issues/588 https://zhuanlan.zhihu.com/p/113009496