# 模块化
# 发展历程
工具 | 时间 |
---|---|
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
vsCMD
:思想和追求上的差别CommonJS
vsES6 module
:值的输出方式的差别CommonJS
是服务端的,同步的;其他是浏览器端的,异步的;ES6 module
是语言本身实现的
# 感悟
- 虽然说CommonJS 、AMD、CMD、ES6 module的实现方式非常相似,但是规范的不同,导致每种方式的内部逻辑、生态、追求、核心思想都相差甚大。
- 每个思想和技术的出现都是为了解决当时技术上的痛点,从实际触发~
# 参考资料
sea.js: https://github.com/seajs/seajs/issues/588 https://zhuanlan.zhihu.com/p/113009496