浅谈模块化草稿
AMD/UMD/CommonJS/ESM
# CommonJs 如何用在浏览器上
require module exports 是 nodejs 运行时提供的接口,所以只能对这些接口进行模拟
核心思想是注册模块(将模块放入数组)和读取模块(读取时通过模块id读取到对应的模块)
模拟倒还好,主要是加载模块a的时候引入模块b 这时候浏览器还得去下载b,下载b完执行然后才进行执行a,这要怎么实现?
有种做法是一开始就对代码做静态分析,将模块与对应的依赖返回给浏览器,必须依赖下载执行完才执行该模块
另外的做法是定一套模板封装模块定义,于是出现了 AMD 和 CMD
AMD 的主要实现为 requireJS ,定义了两个函数 define 和 require ,前者注册模块,后者添加依赖及依赖模块加载完后的回调
AMD推崇依赖前置,在定义模块的时候就要声明其依赖的模块
CMD 的主要实现为 seaJS
CMD推崇就近依赖,只有在用到某个模块的时候再去require
# nodejs 中如何使用 esm
package.json "type" field
or
node --experimental-modules main.mjs
# 浏览器不支持 ES Module 的话,需要用 babel 转,转后有什么不同
# CommonJs 和 ES Module 的区别
CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。
所以
esm 在编译的时候,js引擎会对脚本进行静态分析,遇到import命令就会生成一个只读引用,等到真正执行代码时候再通过这个引用去该模块里面取值,因此原始值变了import加载的值也会变。
cjs 输出拷贝,esm 输出引用
cjs demo
this 值不同,前者为模块对象,后者为 undefined,同时也说明了作用域不同
esm 的 import 有 const 的效果,即基础类型的话不可修改,对象的话不可修改引用地址。动态引用,不会缓存值
esm export default 1
导出的其实是一个 key 为 default 变量,其值为 1
然后可以 import xx from ''
中拿到,这个 xx 随便写都写
而 import * as obj from ''
拿到的是所有引用,包括 default 等;用了这个不能再使用其他的如 * as x,{xx}
不然存在多个相同引用