回顾CMJ和ESM的区别
CMJ的本质可以使用一个函数概括
// require函数的伪代码
function require(path){
if(该模块有缓存吗){
return 缓存结果;
}
function _run(exports, require, module, __filename, __dirname){
// 模块代码会放到这里
}
var module = {
exports: {}
}
_run.call(
module.exports,
module.exports,
require,
module,
模块路径,
模块所在目录
);
把 module.exports 加入到缓存;
return module.exports;
}
所以我们平时在node环境上书写的代码其实是在运行在一个函数中的,我们使用的require
函数其实也是函数的参数了,我可以在node环境中打印一下arguments
console.log(arguments.length)
console.log(arguments)
///输出
5 //参数个数
[Arguments] {
'0': {}, //是module.exports
'1': [Function: require] { //require函数
resolve: [Function: resolve] { paths: [Function: paths] },
main: {
'9': [Function: internalRequire],
id: '.',
path: 'd:\\BaiduNetdiskDownload\\A渡一前端\\联系\\webpack学习\\1-8编译过程\\src',
exports: {},
filename: 'd:\\BaiduNetdiskDownload\\A渡一前端\\联系\\webpack学习\\1-8编译过程\\src\\a.js',
loaded: false,
children: [],
paths: [Array]
},
extensions: [Object: null prototype] {
'.js': [Function (anonymous)],
'.json': [Function (anonymous)],
'.node': [Function (anonymous)]
},
cache: [Object: null prototype] {
'd:\\BaiduNetdiskDownload\\A渡一前端\\联系\\webpack学习\\1-8编译过程\\src\\a.js': [Object]
}
},
'2': { //module对象
'9': [Function: internalRequire],
id: '.',
path: 'd:\\BaiduNetdiskDownload\\A渡一前端\\联系\\webpack学习\\1-8编译过程\\src',
exports: {}, //这个第一参数是相等的
filename: 'd:\\BaiduNetdiskDownload\\A渡一前端\\联系\\webpack学习\\1-8编译过程\\src\\a.js',
loaded: false,
children: [],
paths: [
'd:\\BaiduNetdiskDownload\\A渡一前端\\联系\\webpack学习\\1-8编译过程\\src\\node_modules',
'd:\\BaiduNetdiskDownload\\A渡一前端\\联系\\webpack学习\\1-8编译过程\\node_modules',
'd:\\BaiduNetdiskDownload\\A渡一前端\\联系\\webpack学习\\node_modules',
'd:\\BaiduNetdiskDownload\\A渡一前端\\联系\\node_modules',
'd:\\BaiduNetdiskDownload\\A渡一前端\\node_modules',
'd:\\BaiduNetdiskDownload\\node_modules',
'd:\\node_modules'
]
},
'3': 'd:\\BaiduNetdiskDownload\\A渡一前端\\联系\\webpack学习\\1-8编译过程\\src\\a.js', //文件路径
'4': 'd:\\BaiduNetdiskDownload\\A渡一前端\\联系\\webpack学习\\1-8编译过程\\src' //文件所在文夹路径
}
根据require
是一个函数可知,require
必然是动态导入的,我们可在任何位置使用require
进行模块导入。
ESM除了我们熟知的静态导入,动态导入(返回一个Prmise),还有一个比较奇特的特性,符号绑定,也就是说无论你导出的是一个对象还是一个基础类型的变量他们都是一块内存空间,并且导出的类型是常量。
面试题:CMJ和ESM的区别
参考答案:
- CMJ 是社区标准,ESM 是官方标准
- CMJ 是使用 API 实现的模块化,ESM 是使用新语法实现的模块化
- CMJ 仅在 node 环境中支持,ESM 各种环境均支持
- CMJ 是动态的依赖,同步执行。ESM 既支持动态,也支持静态,动态依赖是异步执行的。
- ESM 导入时有符号绑定,CMJ 只是普通函数调用和赋值
webpack怎么处理CMJ和ESM的导入和导出
由于webpack同时支持CommonJS和ES6 module,所以需要理解它们互操作时webpack是如何处理的。
如果导出和导入使用的是同一种模块化标准,打包后的效果就是标准的的模块化。
不同的模块化标准,webpack按照如下的方式处理。