ESM与Commonjs的差异

2022-04-26  本文已影响0人  Mr无愧于心
  1. CommonJS 模块输出的是一个值的拷贝,ESM输出的是值的引用。
  2. CommonJS 模块是运行时加载,ESM是编译时输出接口。
  3. CommonJS 模块的require()是同步加载模块,ESM的import命令是异步加载,有一个独立的模块依赖的解析阶段。

ESM的import存在提升,且变量像const的 是只读的。

CommonJS 模块输出的是值的拷贝,ESM输出的是值的引用

CommonJS一旦输出一个值,模块内部的变化就影响不到这个值
ESM是动态引用,并且不会缓存值,模块里面的变量绑定其所在的模块

//commonjs

// lib.js
var counter = 3;
function incCounter() {
  counter++;
}
module.exports = {
  counter: counter,
  incCounter: incCounter,
};
// main.js
var mod = require('./lib');

console.log(mod.counter);  // 3
mod.incCounter();
console.log(mod.counter); // 3
//----------------------------------------------------
//ESM
// lib.js
export let counter = 3;
export function incCounter() {
  counter++;
}

// main.js
import { counter, incCounter } from './lib';
console.log(counter); // 3
incCounter();
console.log(counter); // 4
//-------------------------------------

//ESM只是一个“符号连接”,这个变量是只读的,对它进行重新赋值会报错。类似于 const 的特性
counter=1 // TypeError

CommonJS 模块是运行时加载,ESM是编译时输出接口

CommonJS 加载的是一个对象(即module.exports属性),该对象只有在脚本运行完才会生成。而 ESM不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成。

// ESM的import命令具有提升效果,会提升到整个模块的头
foo();
import { foo } from 'my_module';
//以上代码不会报错,因为import命令是编译阶段执行的,在代码运行之前。

Commonjs模块加载ESM模块

CommonJS 的require()命令不能加载 ES6 模块,会报错,只能使用import()这个方法加载。

(async () => {
  await import('./my-app.mjs');
})();

require()不支持 ES6 模块的一个原因是,它是同步加载,而 ES6 模块内部可以使用顶层await命令,导致无法被同步加载。

ESM模块加载Commonjs模块

只能整体加载,不能只加载单一的输出项

// 正确
import packageMain from 'commonjs-package';

// 报错
import { method } from 'commonjs-package';

因为 ES6 模块需要支持静态代码分析,而 CommonJS 模块的输出接口是module.exports,是一个对象,无法被静态分析,所以只能整体加载

上一篇 下一篇

猜你喜欢

热点阅读