原始社会:
在很久很久以前,前端=html+css+js,其中js的代码是最少的,那个时候的 JavaScript 就像个玩具,用处大概就是在侧栏弄个时钟,用 media player 放个 mp3 之类的脚本,代码量不是很多,直接放在 <script> 标签里或者弄个 js 文件引一下就行,日子过得很轻松愉快。
随后的几年,人们开始尝试在一个页面里做更多的事情。容器的显示,隐藏,切换。用 css 写的弹层,图片轮播等等。但如果一个页面内不能向服务器请求数据,能做的事情毕竟有限的,代码的量也能维持在页面交互逻辑范围内。这时候很多人开始突破一个页面能做的事情的范围,使用隐藏的 iframe 和 flash 等作为和服务器通信的桥梁,新世界的大门慢慢地被打开,在一个页面内和服务器进行数据交互,意味着以前需要跳转多个页面的事情现在可以用一个页面搞定。但由于 iframe 和 flash 技术过于 tricky 和复杂,并没能得到广泛的推广。
插件时代:
直到 Google 推出 Gmail 的时候(2004 年),人们意识到了一个被忽略的接口,XMLHttpRequest, 也就是我们俗称的 AJAX, 这是一个使用方便的,兼容性良好的服务器通信接口。从此开始,我们的页面开始玩出各种花来了,前端一下子出现了各种各样的库,Prototype、Dojo、MooTools、Ext JS、jQuery…… 我们开始往页面里插入各种库和插件,我们的 js 文件也就爆炸了。
随着 js 能做的事情越来越多,引用越来越多,文件越来越大,加上当时大约只有 2Mbps 左右的网速,下载速度还不如 3G 网络,对 js 文件的压缩和合并的需求越来越强烈,当然这里面也有把代码混淆了不容易被盗用等其他因素在里面。JSMin、YUI Compressor、Closure Compiler、UglifyJS 等 js 文件压缩合并工具陆陆续续诞生了。压缩工具是有了,但我们得要执行它,最简单的办法呢,就是 windows 上搞个 bat 脚本,mac / linux 上搞个 bash 脚本,哪几个文件要合并在一块的,哪几个要压缩的,发布的时候运行一下脚本,生成压缩后的文件。
CommonJS诞生:
基于合并压缩技术,项目越做越大,问题也越来越多,大概就是以下这些问题:
●库和插件为了要给他人调用,肯定要找个地方注册,一般就是在 window 下申明一个全局的函数或对象。难保哪天用的两个库在全局用同样的名字,那就冲突了。
●库和插件如果还依赖其他的库和插件,就要告知使用人,需要先引哪些依赖库,那些依赖库也有自己的依赖库的话,就要先引依赖库的依赖库,以此类推。
恰好就在这个时候(2009 年),随着后端 JavaScript 技术的发展,人们提出了 CommonJS 的模块化规范,大概的语法是: 如果 a.js 依赖 b.js 和 c.js, 那么就在 a.js 的头部,引入这些依赖文件:
var b = require('./b')
var c = require('./c')
那么变量 b 和 c 会是什么呢?那就是 b.js 和 c.js 导出的东西,比如 b.js 可以这样导出:
exports.square = function(num) { return num * num }
然后就可以在 a.js 使用这个 square 方法:
var n = b.square(2)
大名鼎鼎的NodeJS就是符合CommonJS规范的。
AMD诞生
但是 CommonJS 在浏览器内并不适用。但是 CommonJS 在浏览器内并不适用。因为 require() 的返回是同步的,意味着有多个依赖的话需要一个一个依次下载,堵塞了 js 脚本的执行。所以人们就在 CommonJS 的基础上定义了 Asynchronous Module Definition (AMD) 规范(2011 年),使用了异步回调的语法来并行下载多个依赖项,比如作为入口的 a.js 可以这样写:
require(['./b', './c'], function(b, c) {
var n = b.square(2)
console.log(c)
})
相应的导出语法也是异步回调方式,比如 c.js 依赖 d.js, 就写成这样:
define(['./d'], function(d) {
return d.PI
})
可以看到,定义一个模块是使用 define() 函数,define() 和 require() 的区别是,define() 必须要在回调函数中返回一个值作为导出的东西,require() 不需要导出东西,因此回调函数中不需要返回值,也无法作为被依赖项被其他文件导入,因此一般用于入口文件,比如页面中这样加载 a.js:
<script src="js/require.js" data-main="js/a"></script>
以上是 AMD 规范的基本用法,更详细的就不多说了(反正也淘汰了~)
CMD诞生:
大名远扬的玉伯写了seajs,就是遵循他提出的CMD规范,与AMD蛮相近的,不过用起来感觉更加方便些,最重要的是中文版,应有尽有:seajs官方doc
define(function(require,exports,module){...});
网友评论