NodeJS把javascript引进了服务端,这个时候commonjs模块化出现了,每个模块化设计都要遵循特定的规范,commonjs也是如此:
1、定义全局函数require,通过传入模块标识来引入其他模块
2、用module.exports导出对象对外暴露出文件的AIP,而且导出的必须是对象
3、如果引入的模块有其他模块,会依次加载其他模块
示例:
// a.js const fn=(_v)=>{ alert(_v) } module.exports={fn}; // b.js const My=require('./a.js'); My.fn("test");
同时每个文件里的变量时有作用域的,只在当前文件有用,如果要在其他地方引用,要么暴露出该变量,要么设置全局global.xx ,一般不推荐。
commonjs只能运行在服务端,如果要运行在浏览器端就要解决相互依赖关系的问题,所以AMD就出现了,require.js就是典型的AMD模式,它采用异步方式来加载模块(“异步”只是加载模块文件时是异步,但是依赖关系依旧是同步的),AMD也有固定的规范
define(id?, dependencies?, factory);
1、通过全局函数define来定义模块;
2、id为模块标识,dependencies为所需要的依赖(可以是标识),factory是对应依赖的形参
3、factory暴露AIP有三种方式:return,exports, module.exports
示例:
//c.js define(['md_a', 'md_b'], function(_a, _b) { return { method: function() { _a.fn(); _b.fn(); } } });
AMD模式在加载模块时需要把之前的所有依赖都要加载一遍,在初始化速度较慢。于是CMD模式诞生了,CMD是按需加载,无需所有模块加载完成。典型的是Sea.js。
在CMD规范中,一个文件就是一个模块,比AMD编写更简单
define(function(require, exports, module) { const _a = require('a.js'); const _b=require(b.js); //……… // 通过 exports 对外提供接口 exports.doSomething = ... // 或者通过 module.exports 提供整个接口 module.exports = ... });
每个模式都有自己的规范,表示不爽,所以UMD就诞生了,它其实就是CommonJS和AMD的结合体,一般在做插件或者SDK时通常采用这个模式,既能在服务端允许,也可以在浏览器端支持。
这里还要提一下ES Module模式,这个在我们做单页面项目中经常用到的模式,目前node也支持了。就是通过export导出,通过import导入