CommonJS To ESM

459 阅读1分钟

大家好,我是右子。

由于Bundless构建工具的兴起,所有的模块都是ESM规范的格式化。

目前社区有一部分同事支持ESMCommonJS两种规范,比如lodash和lodash-es。

但是仍有许多比较好的工具只支持CommonJS和UMD,再加上前端工程优化中的tree-shaking概念,目前CommonJS规范转化ESM规范是必要经历的一个阶段。

ESM 与 CommonJS的导入导出的不同

在ESM中,导入导出有两种方式:

  1. 具名导出/导入:Import/Export Name;
  2. 默认导出/导入:Import/Export Default;

示例:

// 具体名
export function foo(){};
import { foo } from './utils';
// 默认名
export default foo;
import foo from './utils';

但在CommonJS中,导入导出其实只有一种方式:

示例1:

function foo(){};
exports.foo = function(){};
// 或
module.exports = foo;

示例2:

exports.name = 'Tesla';
module.exports.name = 'Tesla';

这两种导出形式是完全等价的。

exports的转化规则

正因为如此,两者才有所不同,当exports转换时,既要转化为export {},也要转化为export default {};

示例:

// CJS
function foo(){};
export.foo = foo;

// EMS
export function foo(){};
export default function foo(){};

如何实现呢?

实现的方式也有很多,可以自己手写AST语法转换来实现,或者你也可以借助Babel的能力,你可能会用到babel/parserbabel/generator;

当然现在也有很多成熟的工具,比如rollup中的@rollup/plugin-commonjs。在webpack中也有很多类似的transform-commonjs。

你也可以使用一些在线的能力进行:

  1. cdn.skypack.dev
  2. jspm.org