JavaScript 模块化

JavaScript 模块化的发展历程

任何模块化,都必须考虑的两个问题就是导入依赖和导出接口。

  • CommonJS
    CommonJS 规范规定,每个模块内部有两个变量可以使用,requiremodule
    • require 用来加载某个模块
    • module 代表当前模块,是一个对象,保存了当前模块的信息。
      exports 是 module 上的一个属性,保存了当前模块要导出的接口或者变量,使用 require 加载的某个模块获取到的值就是那个模块使用 exports 导出的值
  • AMD
    • AMD(Asynchronous Module Definition),即 异步模块定义。
    • 浏览器不能兼容CommonJS,于是AMD就出现了。浏览器不能兼容CommonJS的根本原因在于缺少node.JS的四个环境变量:module、exports、requrie、global。
    • AMD 是 RequireJS 在推广过程中对模块定义的规范化产出。
      首先要在 html 文件中引入 require.js 工具库,就是这个库提供了定义模块、加载模块等功能。它提供了一个全局的 define 函数用来定义模块。所以在引入 require.js 文件后,再引入的其它文件,都可以使用 define 来定义模块。
  • CMD
    CMD 是 Sea.js 在推广过程中对模块定义的规范化产出。
    Sea.js 是阿里的玉伯写的。它的诞生在 RequireJS 之后,玉伯觉得 AMD 规范是异步的,模块的组织形式不够自然和直观。于是他在追求能像 CommonJS 那样的书写形式。于是就有了 CMD 。
  • UMD
    • UMD(Universal Module Definition),即 通用模块定义。

    • UMD 是AMD 和 CommonJS的糅合。

      • AMD 模块以浏览器第一的原则发展,异步加载模块。CommonJS 模块以服务器第一原则发展,选择同步加载。它的模块无需包装(unwrapped modules)。 这迫使人们又想出另一个更通用的模式 UMD(Universal Module Definition),实现跨平台的解决方案。
      • UMD 先判断是否支持 Node.js 的模块(exports)是否存在,存在则使用 Node.js 模块模式。再判断是否支持 AMD(define 是否存在),存在则使用 AMD 方式加载模块。
  • ES6 模块
    模块功能主要由两个命令构成:export 和 import。export 命令用于导出模块的对外接口,import 命令用于导入其他模块导出的内容。
规范名称 服务于x端 方式 执行时机 同步异步 模块输出 模块顶层的this指向|
CommonJS 服务端 - - 同步/运行时加载 值拷贝 this指向当前模块
AMD 浏览器端 依赖前置 提前执行(加载完模块后立即执行) 异步加载模块
CMD 浏览器端 依赖就近 延迟执行(加载完模块不立即执行,只是加载,等到需要的时候才会执行) 异步加载模块
ES6 Module 浏览器端&服务端 静态编译(在编译的时候就能确定依赖,编译的时候输出接口) 编译时加载块 值引用 this指向undefined

模块依赖环

ES6、CommonJS循环引用问题
什么是循环引用?循环加载指的是a脚本的执行依赖b脚本,b脚本的执行依赖a脚本。
① CommonJS模块是加载时执行。一旦出现某个模块被“循环加载”,就只输出已经执行的部分,没有执行的部分不会输出。
② ES6模块对导出模块,变量,对象是动态引用,遇到模块加载命令import时不会去执行模块,只是生成一个指向被加载模块的引用

解决

1.在循环依赖的每个模块中先导出自身,然后再导入其他模块
这种解决办法可行的原因是, JavaScript 是一门解释型的语言,在 require 其他模块之前,已经把自身需要导出的部分都导出了,所以即便有模块载入缓存,也不影响最终结果按预期进行。

//a.js
module.exports = {
    A: 'this is a Object'
};
 
let b = require('./B');
//b.js
module.exports = {
    B: 'this is b Object'
};
 
let a = require('./A');
  1. 把重来一遍变成中断
    第二次读取 a.js 的时候 Nodejs 该怎么处理呢, 如果像浏览器一样的话, 应该重头再解析一遍, 又读到 require b.js 跑进去再重来。Nodejs 称为 unfinished copy, 第二进入 a.js 模块的时候, 从require b.js 的后面继续往下读取, 这样就将环解开又回到了原先串行的解析方式, 代价就是你得知道 require 前后都写了什么, 尤其是涉及 exports 出去的值, 因为执行顺序问题, 两次的值并不相同。
    不过如果我们不想中断, 就想从头到尾读呢?
  2. 模块解析和模块加载分开处理
    那我们就需要将模块解析和模块加载分开处理, 比如我们 ES6 Module 带来的 import。因为代码的执行分成了两个阶段, 意味着无论你 import 写在哪都会比其他代码先被读取, 这也就解决了 require 前后代码执行顺序导致 exports 值不一致的问题。
    通过解析加载分离, 我们就可以先解析模块的依赖关系, 而避免去读取实际的模块代码。在 a.js 中我们读取到 import 'b.js', 这时候我们可以给 b.js 添加一个 State, 并将其值设为 'Linked', 表示 b.js 已经被读取了, 然后从 b.js 读取到 import a.js, 我们再将 a.js 的 State 设为 'Linked', 然后又回到 a.js, 发现 b.js 已经是 Linked 了, 跳过, 继续读取 c.js , 通过状态标记就避免了循环依赖
//a.js
import b from 'b.js'
import c from 'c.js'

//b.js
import a from 'a.js'

相关文章

  1. JS模块化的发展历程,CommonJS、AMD、CMD、UMD、ES6模块化
  2. 前端科普系列-CommonJS:不是前端却革命了前端
  3. JS模块化的各种规范 之 CJS、AMD、CMD、UMD、ESM
  4. Node.js中的模块循环依赖及其解决
  5. 从 Nodejs 如何解决模块循环依赖问题来一点关于模块的发散思考
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,444评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,421评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,363评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,460评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,502评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,511评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,280评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,736评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,014评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,190评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,848评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,531评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,159评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,411评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,067评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,078评论 2 352

推荐阅读更多精彩内容