前端模块化的演变
2017, Nov 09
commonjs
- commonjs是专攻服务器的,由于它的api简单直接,在nodejs中推广开来。
- commonjs规范是无法用在浏览器的,主要原因在于: 在服务端和浏览器环模块的加载方式截然不同。 服务器中加载一个模块直接在硬盘中读取文件就可以了 但浏览器环境需要动态的创建script标签,然后异步加载模块,并且要等到模块执行完成,才能够使用其中的API.
浏览器端模块化的尝试
1 直接把commonjs闺房封装到浏览器环境(browserify)
2 异步加载模块,依赖前置(AMD)
3 异步加载模块,按需加载(CMD)
1)AMD (requirejs)
- AMD思想,异步加载所需的模块,并在回调函数中执行剩下的逻辑,这正是我们开发浏览器习惯的方式。
AMD规范包含一下规则:
1用全局函数define来定义模块,define(id, dependencies, factory)
2id为模块标识,dependencies为依赖的模块,factory为回调函数,参数中要传递对应的形参。# define('x', ['A','B','C'], function(a,b,c){})
3如果dependencies不写,默认为[‘require’, ‘exports’, ‘module’]。
4factory函数向外暴露:# define('x', ['A','B','C'], function(a,b,c){ //return {} //exports.xxx = xxx (==commonjs规范) //module.exports = xxx })
5若factory为对象,则该对象则为暴露的内容。
-
requirejs的缺点
1,requirejs不仅预加载模块,而且都执行完了才进入到回调函数。这个性能消耗是值得注意的。
2,依赖模块的执行顺序和书写顺序不一定一致如何让模块预先加载,需要才执行呢??
2)CMD (seajs)
- cmd是commonjs另外的一种模块加载方案
1,一个文件一个模块,所以经常就用文件名作为模块id
2,CMD推崇依赖就近,所以一般不在define的参数中写依赖,在factory中写
3,factory是一个函数,有三个参数,function(require, exports, module)
4,require 是一个方法,接受 模块标识 作为唯一参数,用来获取其他模块提供的接口:require(id)
5,exports 是一个对象,用来向外提供模块接口
6,module 是一个对象,上面存储了与当前模块相关联的一些属性和方法
// 定义模块 myModule.js
define(function(require, exports) {
// 获取模块 a 的接口
var a = require('./a');
// 调用模块 a 的方法
a.doSomething();
});
// 加载模块
seajs.use(['myModule.js'], function(my){
});
- 貌似同步加载模块,实则代码在运行时,
需要遍历所有的require关键字,找出后面的依赖。具体做法是将function toString后,用正则匹配出require关键字后面的依赖。
仅仅在表现形式上,AMD依赖前置,CMD就近依赖。