Open shizhihuaxu opened 3 years ago
CJS 使用不同的算法是因为它从文件系统加载文件,这耗费的时间远远小于从网络上下载。因此 Node 在加载文件的时候可以阻塞主线程,而不造成太大影响。而且既然文件已经加载完成了,那么它就可以直接进行实例化和运行。所以在 CJS 中实例化和运行并不是两个相互独立的阶段,而是连续不间断的。
在 CJS 中,整个导出对象在导出时都是值拷贝。即,所有的导出值都是拷贝值,而不是引用。所以,如果导出模块内导出的值改变了,导入模块中导入的值也不会改变。
AMD/CMD 是 CommonJS在浏览器端的解决方案。
CommonJS是同步加载(代码在本地,加载时间基本等于硬盘读取时间)。
AMD/CMD是异步加载(浏览器必须这么做,代码在服务端)
UMD 是 AMD 与 CommonJS 的结合,跨平台的解决方案;UMD先判断是否支持Node.js的模块(exports)是否存在,存在则使用Node.js模块模式。再判断是否支持AMD(define是否存在),存在则使用AMD方式加载模块。
js 的模块化标准
解决什么问题
解决变量管理,变量作用域与访问,变量共享的问题,提供一种更好的方式管理变量和函数,将相关的变量和函数放在一个模块中,模块作用域,共享数据。
对外暴露的过程为导出,导入此模块的模块就可以显示的声明依赖此模块的数据,是一种明确的依赖关系
从入口文件,根据依赖关系加载各个依赖文件,但是不能直接使用,而是进行解析,将模块关系记录下来,解析后将代码和状态(变量的实际值)结合起来,形成模块实例。模块加载会从入口文件开始,最终生成完整的模块实例关系图。
同其它模块化系统有什么区别
ESM 生成模块实例的过程:
为什么说 esm 是异步的?
模块定位符 (import from 'specifier', export)
动态 import() ,实际上把加载的模块当成了入口文件,会生成一个新的模块依赖关系树,与非 动态import的依赖关系树共有的模块会共享同一个模块实例,因为加载器会缓存模块实例,并且再全局范围内一个模块只会存在一个模块实例。
加载器会缓存模块,一个模块文件只会被下载一次,即使有多个模块依赖它。使用模块映射,每个全局作用域有一个独立的模块映射,加载文件后会将 url 记录在模块映射中,如果有其它模块也依赖于这个模块,会自动跳过下载。
解析目标(解析方式),对同一个文件不同的解析目标会生成不同的结果
ESM 则使用称为实时绑定(Live Binding)的方式。导出和导入的模块都指向相同的内存地址(即值引用)。所以,当导出模块内导出的值改变后,导入模块中的值也实时改变了。
模块导出的值在任何时候都可以能发生改变,但是导入模块却不能改变它所导入的值,因为它是只读的。
CommonJS(Nodejs,同步)
CJS 使用不同的算法是因为它从文件系统加载文件,这耗费的时间远远小于从网络上下载。因此 Node 在加载文件的时候可以阻塞主线程,而不造成太大影响。而且既然文件已经加载完成了,那么它就可以直接进行实例化和运行。所以在 CJS 中实例化和运行并不是两个相互独立的阶段,而是连续不间断的。
在 CJS 中,整个导出对象在导出时都是值拷贝。即,所有的导出值都是拷贝值,而不是引用。所以,如果导出模块内导出的值改变了,导入模块中导入的值也不会改变。
AMD/CMD 是 CommonJS在浏览器端的解决方案。
CommonJS是同步加载(代码在本地,加载时间基本等于硬盘读取时间)。
AMD/CMD是异步加载(浏览器必须这么做,代码在服务端)
UMD 是 AMD 与 CommonJS 的结合,跨平台的解决方案;UMD先判断是否支持Node.js的模块(exports)是否存在,存在则使用Node.js模块模式。再判断是否支持AMD(define是否存在),存在则使用AMD方式加载模块。
ES Module(esm,ECMAScript Nodule,异步)
js 的模块化标准
解决什么问题
解决变量管理,变量作用域与访问,变量共享的问题,提供一种更好的方式管理变量和函数,将相关的变量和函数放在一个模块中,模块作用域,共享数据。
对外暴露的过程为导出,导入此模块的模块就可以显示的声明依赖此模块的数据,是一种明确的依赖关系
从入口文件,根据依赖关系加载各个依赖文件,但是不能直接使用,而是进行解析,将模块关系记录下来,解析后将代码和状态(变量的实际值)结合起来,形成模块实例。模块加载会从入口文件开始,最终生成完整的模块实例关系图。
同其它模块化系统有什么区别
ESM 生成模块实例的过程:
为什么说 esm 是异步的?
模块定位符 (import from 'specifier', export)
动态 import() ,实际上把加载的模块当成了入口文件,会生成一个新的模块依赖关系树,与非 动态import的依赖关系树共有的模块会共享同一个模块实例,因为加载器会缓存模块实例,并且再全局范围内一个模块只会存在一个模块实例。
加载器会缓存模块,一个模块文件只会被下载一次,即使有多个模块依赖它。使用模块映射,每个全局作用域有一个独立的模块映射,加载文件后会将 url 记录在模块映射中,如果有其它模块也依赖于这个模块,会自动跳过下载。
解析目标(解析方式),对同一个文件不同的解析目标会生成不同的结果
ESM 则使用称为实时绑定(Live Binding)的方式。导出和导入的模块都指向相同的内存地址(即值引用)。所以,当导出模块内导出的值改变后,导入模块中的值也实时改变了。
模块导出的值在任何时候都可以能发生改变,但是导入模块却不能改变它所导入的值,因为它是只读的。