前端技术

ESM vs CJS

2023-02-05  本文已影响0人  吴摩西

学自:https://webreflection.medium.com/cjs-vs-esm-5f8b90a4511a

安全性

ESM 较 CJS 更加安全。

// module.js
export let a = 'a';
export let b = 'b';
export let c = 'c';
// index.js
import * as esmModule from './module.js';
esmModule.a = 'z';
console.log(esmModule);
// result:
esmModule.a = 'z';
            ^
TypeError: Cannot assign to read only property 'a' of object '[object Module]'

作为对比,CJS 可以修改 modules.export 中的值。

测试

CJS 相较于 ESM 更容易测试。

require('module');
// some stuff
// module cache invalidation
delete require.cache[require.resolve('module')];
// some other stuff
require('module');

Treeshaking

ECMAScript 可以支持 Treeshaking,CommonJS 不行。ECMAScript 现实中也没能从 Treeshaking 中获利。因为浏览器需要下载对应的资源(node 需要阅读对应的代码)才能知道如何 Treeshaking。事实上,应该只有 AOT (Ahead of Time) 编译器可以从 Treeshaking 获利。

幸运的是,在语法分析阶段(parsing phase),执行引擎可以知道哪些代码需要处理和优化,哪些不能。但是这引起了一些误解。

async function loadMyModule() {
  const { 
    default: defaultImport,
    namedExport1,
    namedExport2
  } = await import('./mixedExportModule.js');
  // ...
}
loadMyModule();

可见 CJS / ESM 在 Treeshaking 方面可能都不是赢家。如果一个模块从 Treeshaking 中获利很多,可能有更好的方案,把这个模块切分成多个模块或者可以单独引入的子模块。

live binding + default

ESM 支持 live binding,而 CommonJS 不支持。

ESM 在 export 变量时,是以引用的方式被引入的。这与 CommonJS 的方式有所不同。当模块内的变量值有所变动时,引入方再读取变量值时可以获得新的值。

MIME 类型

只要 HTTP 中相关的 header mime 类型是对的,ESM 不关心文件后缀名。例如 .js 在 NodeJS 世界上是一个 CJS 类型文件。 在Web 中 .gif 的文件,也可以用 application/javascript 类型返回。

结论

谈论一下技术细节可能比简单说 ESM 和 CJS 哪个更好有意义。

上一篇下一篇

猜你喜欢

热点阅读