大家好,我是右子。
由于Bundless构建工具的兴起,所有的模块都是ESM规范的格式化。
目前社区有一部分同事支持ESM
与CommonJS
两种规范,比如lodash和lodash-es。
但是仍有许多比较好的工具只支持CommonJS和UMD,再加上前端工程优化中的tree-shaking概念,目前CommonJS规范转化ESM规范是必要经历的一个阶段。
ESM 与 CommonJS的导入导出的不同
在ESM中,导入导出有两种方式:
- 具名导出/导入:Import/Export Name;
- 默认导出/导入: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/parser
和babel/generator
;
当然现在也有很多成熟的工具,比如rollup中的@rollup/plugin-commonjs。在webpack中也有很多类似的transform-commonjs。
你也可以使用一些在线的能力进行:
- cdn.skypack.dev
- jspm.org