js模块化发展历程
js作为一个非主流语言发展到现在如此热门的语言,一定经历了很多的变迁,我们从模块化方面来了解下js的发展。
直接定义
这时候的前端也没有模块化的概念,当然js文件之间也没有太多的束缚,只是简单的堆砌script标签,没有全局变量与局部变量的概念,定义的变量都是全局的。因此很容易出现,b文件改了a文件中的变量内容,却不知道,照成后期开发难,维护难的问题,甚至加个变量名都得全局搜索下。
渐有模块
也许是意识到模块化的问题后,开始逐渐减少全局变量,并增加单个js的内聚性。
减少全局变量
开始减少全局暴露的js变量,
var glo = {
name: '',
age: 123
};
增加局部变量
jquery的源码就非常典型,利用自执行函数,减少变量的暴露,
(function() {
// ....
window.what = what;
})();
私有变量模拟
我们都知道js是没有私有变量的概念的,但是可以模拟出来:
var A = function() {
var _a = 0;
this.add = function() {
_a++;
}
this.getA = function() {
return _a;
}
}
var aaa = new A();
aaa.getA();
aaa.add();
aaa.add();
aaa.getA();
利用function的作用域,完美的模拟了私有变量。 我们开始意识到前端模块化的重要性,当然这是好事。
蓬勃发展
依赖注入
用过angular的都知道,借鉴java的概念,angular中模块化很重要的一块。
commonjs
随着nodejs的出现,js走向了服务端,可是作为服务端的语言没有模块化的设计,那一定是非常混乱的。于是commonjs规范就脱颖而出了。
// a.js
module.export = {};
在入口文件app.js中,
// app.js
var a = require('./a.js');
那么前端是否能照搬这一套呢?其实是不行的,因为require是同步加载的,正常清空下后端要加载的文件都是在服务器上的,访问都是非常快的。而前端的资源都是通过网络加载的,不确定性和延迟都比较高,所以,这套规范不适用于前端。
requirejs
RequireJS 是一个JavaScript模块加载器,是AMD规范最好的实现者之一。
require(['moduleA', 'moduleB', 'moduleC'], function (moduleA, moduleB, moduleC){
// ...
});
requireJS会异步加载这三个模块,等都加载完成后,触发对应的回调事件。
seajs
SeaJS是一个遵循CMD规范的JavaScript模块加载框架,可以实现JavaScript的模块化开发及加载机制。
amd与cmd和commonjs详细内容可以查看这篇文章,AMD、CMD和CommonJS规范。
UMD
兼容了 CommonJS 与 Amd,其核心思想是,如果在 commonjs 环境(存在 module.exports,不存在 define),将函数执行结果交给 module.exports 实现 Commonjs,否则用 Amd 环境的 define,实现 Amd。结构如下:
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['b'], factory);
} else if (typeof module === 'object' && module.exports) {
// Node. Does not work with strict CommonJS, but
// only CommonJS-like environments that support module.exports,
// like Node.
module.exports = factory(require('b'));
} else {
// Browser globals (root is window)
root.returnExports = factory(root.b);
}
}(this, function (b) {
//use b in some fashion.
// Just return a value to define the module export.
// This example returns an object, but the module
// can return a function as the exported value.
return {};
}));
标准化
模块化终于在es6中形成了标准,export和import方式也逐步被我们使用。
工具
在我们常用的打包工具webpack中,是可以选择默认的打包方式的,支持commonjs和requirejs,umd方式也是支持的。