commonjs和es6的module的区别

这篇文章主要讲一下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自己做了处理,所以你写的时候可以省略扩展名,但是按照规范还是应该保留扩展名。

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语句是不允许用动态路径的。