这篇文章主要讲一下CommonJS和ES modules的四个主要的区别。
第一个区别:
如果想在导出时使用别名,ES Modules要写成:
export { a as d, b as e, c as f, }
而对应的CommonJS的写法是:
module.exports = { d: a, e: b, f: c, }
第二个区别是,CommonJS在require文件的时候采用文件路径,而且可以忽略.js文件扩展名。比方说,require(‘./say.js’)完全可以写成require(‘./say’)。
但是ES Modules在import的时候采用的是URL规范就不可以省略文件的扩展名,必须写完整的文件名import {say} from ‘./say.mjs’,这个.mjs扩展名是不可以省的。
如果你用Babel编译的方式将ES Modules编译成CommonJS,因为Babel自己做了处理,所以你写的时候可以省略扩展名,但是按照规范还是应该保留扩展名。
第三个区别是,ES Modules的export和import不可以放在块级作用域或函数作用域中,只能写在最外层。比如:
if(condition) { import {a} from './foo'; } else { import {a} from './bar'; }
这种写法,在ES Modules中是不允许的。但是,像下面这种写法在CommonJS中是被允许的。
let api; if(condition) { api = require('./foo'); } else { api = require('./bar') }
其实,CommonJS的require可以写在任何语句块中,特别灵活。
第四个区别,require是一个函数调用,路径是参数字符串,它可以动态拼接,比如:
const libPath = ENV.supportES6 ? './es6/' : './'; const myLib = require(`${libPath}mylib.js`);
但是ES Modules的import语句是不允许用动态路径的。