js中现在比较成熟的模块加载方案(js模块加载机制)

随着项目越来越复杂,功能越来越庞大,需要引入的公共数据也就越来越多,所以「模块」的解决方案应用而生。

「CommonJS」「AMD」「CMD」「ES6」,它们都是模块加载方案,指明了模块文件的写法、用法。
CommonJS 规范
CommonJS 的模块加载方案是「同步执行」的,必须前面模块加载完,才能继续执行下一步。服务器端读取数据是从硬盘读取,所以速度就取决于硬盘加载文件的速度,这种规范在服务器端是主流选择。
示例:
//math.jsmodule.exports.add = (x, y) => x + y;//program.jsvar math = require(\\\'math\\\');math.add(1,2)
CommonJS 规范规定每个文件都是一个模块,module是代表当前模块的变量,这个变量是一个对象。它的 exports 属性是对外的接口。
AMD 规范
AMD 是「Asynchronous Module Definition」的缩写,意思是「异步模块定义」,它是 CommonJS 模块规范的一个延伸。AMD 规范是浏览器端模块化方案的主流选择,因为浏览器加载文件的速度取决于网络环境,所以「异步」非常关键。
AMD 规范很简单,它只有一个 define 函数:
示例:
define(id?, dependencies?, factory)
模块id和依赖是可选的,factory 的内容就是实际代码内容。
//定义模块 demo.jsdefine(function(){  var exports = {};  exports.sayHello = function(){    alert(\\\'Hello from module:\\\' + module.id)  }  return exports;})//使用requite(\\\'demo\\\',function(demo){  demo.sayHello(); });
AMD 需要 define 来明确一个模块,使用时,仅在需要的时候被引入。如果想在项目中使用,可以使用 RequireJS 。
CMD 规范
CMD 是阿里巴巴玉伯提出来的解决方案,与 AMD规范的区别在于开发方式不同。
AMD 是提前执行,CMD 是延迟执行(使用到再执行),后期 AMD 规范的 RequireJS 2.0版本,也支持了延迟执行。
AMD 是依赖前置,CMD 是依赖就近。在 API 的使用上,CMD 职责更单一(玉伯自己说的)。
如果想在项目中使用,可以使用 SeaJS 。
ES6规范
在 ES6 之前模块加载方案主要有 CommonJS 和 AMD 两种规范,前者多用于服务器,后者多用于浏览器。
ES6 的设计思想是尽量静态化,在编译时就能确定模块依赖关系,以及输入输出的变量。
主要有两个命令构成「export」「import」,export 用于输出接口,import 用于输入其他模块功能。
//模块 user.jslet name = \\\'cuishunbiao\\\';let sex = \\\'男\\\';let work = \\\'web\\\';export {  name,  sex,  work}//main.jsimport {name,sex,work} from \\\'./user.js\\\'console.log(name,sex,work);
ES6 支持模块整体加载,用「*」号来指定一个对象,所有输出值都加载在这个对象上。
ES6 和 CommonJS 有一个本质的不同,CommonJS 输出的是一个值的拷贝,而 ES6 输出的是值的引用。
CommonJS 输出值以后,模块内部变化,就不会再影响到它了。
举例说明:定义一个文件,声明 counter 变量 和 addCounter 方法,counter 初始值为 1 ,addCounter 方法的则是加1。
// lib.jsvar counter = 1;function addCounter(){  counter++}module.exports = {  counter: counter,  addCounter: addCounter}
//main.jsvar counter = require(\\\'./lib\\\').counter;var addCounter = require(\\\'./lib\\\').addCounter;console.log(counter);//1addCounter();console.log(counter);//1 输出值不受影响
counter 的输出值不受影响。但 ES6 生成的是动态引用,需要用到的时候会去模块中取值。
//lib.jsexport let counter = 1;export function addCounter(){  counter++}//main.jsimport {counter,addCounter} from \\\'./lib\\\';console.log(counter);//1addCounter();console.log(counter);//2 改变了输出值
兼容多种模块规范
为了让同一个模块可以运行在前后端,类库开发者要将代码放在一个闭包内,能够兼容Node、AMD、CMD以及常见的浏览器环境。
;(function (name, definition) {  // 检测上下文环境是否为AMD或CMD  var hasDefine = typeof define === \\\'function\\\',    // 检查上下文环境是否为Node    hasExports = typeof module !== \\\'undefined\\\' && module.exports;
if (hasDefine) { // AMD环境或CMD环境 define(definition); } else if (hasExports) { // 定义为普通Node模块 module.exports = definition(); } else { // 将模块的执行结果挂在window变量中,在浏览器中this指向window对象 this[name] = definition(); }})(\\\'hello\\\', function () { var hello = function () {}; return hello;});
参考资料:
《深入浅出 Node.js》
《ES6标准入门》
https://github.com/amdjs/amdjs-api/wiki/AMD
https://github.com/seajs/seajs/issues/242
https://justineo.github.io/singles/writing-modular-js/
https://segmentfault.com/a/1190000017878394
https://zh.wikipedia.org/wiki/CommonJS

https://my.oschina.net/qufei1993/blog/4701150


图片授权基于 www.pixabay.com 相关协议

原创文章,作者:小道研究,如若转载,请注明出处:https://www.sudun.com/ask/34590.html

(0)
小道研究's avatar小道研究
上一篇 2024年4月10日 下午5:20
下一篇 2024年4月10日 下午5:22

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注