为什么需要模块化?

全部代码写在一个 js 文件中,耦合度高,全局变量污染,代码复杂,难维护,不安全,所以出现了模块化。
模块化,就是将一个复杂的程序依据一定的规则/规范封装成多个文件,最终再组合在一起。模块的内部数据是私有的,通过向外部暴露接口与其他模块通信。

模块化规范是什么?

引入 js 文件越来越多,请求过多,还是会有全局变量污染、变量重名、依赖关系复杂无法保证顺序等问题,因此有了模块化规范。
模块化规范有 CommonJS、AMD、CMD、ES6 四种。

CommonJS AMD CMD ES6
用于服务器端,即 nodejs 环境,模块加载是同步的 用于浏览器端,模块加载是异步的 用于浏览器端,模块加载是异步的类似 AMD
在浏览器中 使用 Browserify 编译打包 依赖于 Require.js 使用 Babel 将 ES6->ES5,使用 Browserify 编译打包 js

CommonJS

CommonJS 语法

module.exports = xxx
// 或
exports.x = xxx
require("xxx")

在 node 环境中运行 CommonJS

node app.js

在浏览器中运行 CommonJS

若想在浏览器中运行 CommonJS,在 index.html 直接引入 app.js,浏览器是无法理解的,需要使用 Browserify 将 app.js 编译打包成浏览器可识别的语法。

npm install browserify -g
browserify app.js -o dist/bundle.js
<script type="text/javascript" src="./dist/bundle.js"></script>

关于 module.exports 和 exports 的区别,请看这篇你搞懂module.exports和exports了吗?

AMD

AMD 语法

// 定义没有依赖的模块
define(function(){
	return module
})
// 定义有依赖的模块
// m1和m2对应依赖的模块module1和module2返回的
define([module1,module2], function(m1,m2){
	return module
})
require([module1,module2], function(m1,m2){})

CMD(不常用,不重要)

CMD 语法

// 定义没有依赖的模块
define(function(require, exports, module){
	exports.xxx = value
	module.exports = value
})
// 定义有依赖的模块
define(function(require, exports, module){
 // 引入依赖模块(同步)
 var module2 = require('./module2')
 // 引入依赖模块(异步)
 require.async('./module3', function(m3){
 
 })
 // 暴露模块
 exports.xxx = value
})
define(function(require){
	var m1 = require('./module1')
 m1.show()
})

ES6

ES6语法

最简单,export,import,默认导出 export default { }

在浏览器中运行ES6

  1. 安装 babel、browserify

    npm i babel-cli browserify -g
    npm i babel-preset-es2015 --save-dev
  2. 添加 .babelrc 文件

    // .babelrc
    {
        "presets": ["es2015"]
    }
  3. 编译、打包

    babel js -d lib // 使用babel将ES6编译为ES5
    browserify lib/app.js -o dist/bundle.js
  4. 页面引入打包后的文件

    <script type="text/javascript" src="./dist/bundle.js"></script>