我们先来看下ejs和cjs的区别在哪
//cjs写法 a.js
var a = 1;
var b = 2;
setTimeout(function(){
a = 3;
b = 4;
}, 2000)
module.exports = {
a: a,
b: b
}
var a = require('a.js');
console.log(a.a) // 1
console.log(a.b) // 2
setTimeout(function(){
console.log(a.a) // 1
console.log(a.b) // 2
}, 5000)
//esmx写法 a.js
var a = 1;
var b = 2;
setTimeout(function(){
a = 3;
b = 4;
}, 2000)
export defalut {
a: a,
b: b
}
import a from 'a.js';
console.log(a.a) // 1
console.log(a.b) // 2
setTimeout(function(){
console.log(a.a) // 3
console.log(a.b) // 4
}, 5000)
可以看出ejs和cjs写法产生了不同效果。
cjs是执行到require语句才会导入模块,它导入的是模块的拷贝,导入一次之后就会被缓存,后面再导入是缓存的版本
esm 模块在编译阶段就可以分析出导出的结果(导入会先于正常的执行流执行),导出的结果是值得引用,所以对原模块的更改会影响导出值
可以看个例子:
// a.js
console.log('a')
// b.js
console.log('b')
var a = require('a.js') // b a
// c.js
console.log('c')
import 'a.js' // a c
怎么在ems中使用cjs呢?
esm中 export 导出的是一个模块 export default a 实际导出的是{default: a}
import a, {b, c}from 'b.js' 其实a导入的是 b模块导出来的default属性
babel处理esm中使用cjs
// a.js
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
})
exports.defalut = exports.a = exports.b = void 0;
var a = 1;
exports.a = a
var b = 2;
exports.b = b;
var _default = 3l
exports.defalut = _default;
// b.js
import {a, b} from 'a.js'
console.log(a)
console.log(b)
babel处理后:
var _lib = require('lib');
console.log(_lib.a)
console.log(_lib.b)
// c.js
import lib from 'a.js'
使用整体导入的,babel处理后:
'use strict';
var _lib = _interopRequireDefault(require('a.js'));
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {defalut: obj}
}
可以看出如果export上挂载了__esModule属性,所有在导入时,如果是es module直接返回,如果不是则当做cjs处理,整体挂载在一个对象的default属性上,统一。