ESM vs CJS

作者: 吴摩西 | 来源:发表于2023-02-05 10:34 被阅读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 更容易测试。

    • CJS 支持 缓存无效
    • 分析工具可以挂载在任何模块上
    • 代码执行时,可以分析第三方组件的指标和变化
    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),执行引擎可以知道哪些代码需要处理和优化,哪些不能。但是这引起了一些误解。

    • CJS 和 ESM 都支持动态引入代码,动态引入代码事实上打败了 treeshaking 的优势。
    async function loadMyModule() {
      const { 
        default: defaultImport,
        namedExport1,
        namedExport2
      } = await import('./mixedExportModule.js');
      // ...
    }
    loadMyModule();
    
    • CJS / ESM 都支持对某些模块有特定的 export 路径。例如,lo-dash 可以把所有的模块在一个文件中 export,也可以用单独的文件 export 每个模块。

    可见 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 哪个更好有意义。

    相关文章

      网友评论

        本文标题:ESM vs CJS

        本文链接:https://www.haomeiwen.com/subject/gaivhdtx.html