随着前端js代码复杂度的提高,JavaScript模块化这个概念便被提出来,前端社区也不断地实现前端模块化,直到es6对其进行了规范,下面就介绍JavaScript模块化是如何一步一步地发展起来的,并且也会主要对这些模块化方式做一个简单的比较。
模块化的目的:
1、代码复杂度随着项目的扩大而增加
2、减少模块之间的耦合
3、希望减少http请求
最原始的js写法,将所有的函数变量都定义在全局变量下,这种写法污染全局空间,很可能会导致变量命名冲突。
接着出现模块模式的写法,模块模式使用了立即执行函数,并通过函数参数传递需要的模块变量。模块模式勉强满足了封装的需求。
然而只有封装是不够的,还需要加载。html中的js文件加载,难以维护,依赖过多,同时请求也过多。
接下来出现了commonJS模块规范,让js跳出了浏览器环境,定义了module 、 exports 、 require 、 global 实现模块的定义和引用。通过CommonJS,每个JS文件独立地存储它模块的内容(就像一个被括起来的闭包一样)。在这种作用域中,我们通过 module.exports 语句来导出对象为模块,再通过 require 语句来引入。
CommonJS以服务器优先的方式来同步载入模块,假使我们引入三个模块的话,他们会一个个地被载入。它在服务器端用起来很爽,可是在浏览器里就不会那么高效了。
CommonJS已经挺不错了,但假使我们想要实现异步加载模块该怎么办?答案就是Asynchronous Module Definition(异步模块定义规范),简称AMD.
AMD是并行加载所有依赖的模块, 并完成执行后, 再开始执行其他代码。
在一些同时需要AMD和CommonJS功能的项目中,你需要使用另一种规范:Universal Module Definition(通用模块定义规范)。
UMD创造了一种同时使用两种规范的方法,并且也支持全局变量定义。所以UMD的模块可以同时在客户端和服务端使用。
最后再ES6中定义了模块,使用import和export来导出引入模块。
现在出现了webpack模块打包器,使用webpack在打包模块的同时进行优化,通过使用loaders可以将把源模块转换成通用模块,使用plugins将模块。webpack 本身维护了一套模块系统,这套模块系统兼容了所有前端历史进程下的模块规范,包括 amd commonjs es6 等。babel 能提前将 es6 的 import 等模块关键字转换成 commonjs 的规范。这样 webpack 就无需再做处理,直接使用 webpack 运行时定义的 webpack_require 处理。