前言
在目前的前端开发中, 常用的模块化主要是commonJS和ES中的Module。本文也主要是谈谈这两种模块化方式。
commonJS
该模块化方案主要用于node.js的后台服务器开发。 由于加载文件时, 很快就不存在异步问题。该方案中, 使用exports和module.exports导出模块。该模块导出为一个对象。 使用require方法导入模块。 在node执行到require时, 就会阻塞式的运行被导入的文件。 然后运行结果值传递给export对象。
//a.js
exports.a = 'a'
//b.js
var a == require('a.js')//导出一个对象,
exports == module.exports = {}
其实我们就是在module.exports的对象上添加属性, 然后被导入的时候, 就是导入这个module.exports对象。
ES6模块
其实社区中, 模块化的解决方案很多。 其中commonJS主要用于服务器。 AMD主要用于浏览器。 ES6模块统一了javascript的模块化方案。 让其在服务器与浏览器中都可以使用。 该方案中, 使用export 和export default完成导出模块(显示指定输出的代码, 而不是像commonJS那样导出一个对象)。 使用import来完成导入模块。
//a.js
export default xxx
export var a = 'a'
//b.js
import x, {a as c} from 'a.js'
import * from 'a.js' //无法导入默认导出
module circle from './circle.js' //整体输入模块的作用
这里需要说一点就是import会被提升。 然后创建一个只读引用。 然后在真正需要用到该模块时才去执行这个模块的代码。
不同点
语法不同
commonJS 的语法: exports 、 module.exports、require ES6模块: export 、export default 、import 、module
模块加载的实现不同
commonJS模块输出的是一个值的拷贝, ES6模块输出的事值的引用。 所以commonJS导入的时候就会去执行, 然后把执行的结果返回回来。 ES6就只是生成一个只读的引用。不会去具体执行代码
ES6模块的转码
目前的开发模式很多都是使用在本地开发然后打包上线, 对于这样的开发模式, 我们两种方案都可以使用。 但是在浏览器中直接使用模块化, 目前是不行的。 需要使用其他的方式来使其支持。 例如SystemJS,它是你有一个垫片库, 可以在浏览器内加载ES6模块、AMD模块和CommonJS模块, 将其转为ES5格式。
<script src="systtem.js"></script>
<script>
System.import('./app')//当前目录想的app.js。它可以是ES6模块文件, System.import会自动将其转码。
System.import使用异步加载返回一个Promise对象
</script>