JS 模块化
- 什么是模块化?
将一个复杂的程序依据一定的规则(规范)封装成几个块(文件), 并进行组合在一起
- 模块化的好处
1.提高复用性
2.高可维护
3.更好的分离,按需加载
4.避免命名冲突
- 模块化的缺点
1.增加请求
2.依赖过多
3.难以维护
CommonJS
- 说明
在服务器端: 模块的加载是运行时同步加载的
在浏览器端: 模块需要提前编译打包处理 (依赖Browserify)
- 基本语法
## 暴露
//文件中会生成module对象,exports === module.exports
//暴露的模块到底是什么? 暴露的本质是 exports
module.exports = value (单个暴露)
exports.xxx = value (多出暴露)
## 引入 require
//第三方模块
require('path')
//自定义模块:
require('./js/modules/module1')
注意:后缀js 不需要写 写了也可以
- 实现
在服务器端实现:Node.js
浏览器端实现: Browserify (也称为CommonJS在浏览器端的实现)
通过browserify 编译输出
browserify js/src/app.js -o js/dist/bundle.js
在hmtl里面引入bundle.js 即可
tips:不需要新建dist文件夹 ,browserify会帮助我们创建
区别:
Node.js运行时动态加载模块(同步)
Browserify是在转译(编译)时就会加载打包(合并)require的模块
AMD 异步加载
- 说明
Asynchronous Module Definition(异步模块定义)
专门用于浏览器端, 模块的加载是异步的 (依赖于require.js)
- 语法
## 暴露 define
//定义没有依赖的模块
define(function(){
return 模块
})
//定义有依赖的模块
define(['module1', 'module2'], function(m1, m2){
return 模块
})
## 引入 require
require(['module1', 'module2'], function(m1, m2){
使用m1/m2
})
- 实现
依赖于require.js
http://www.requirejs.cn/
- 配置
## html
<script src="js/libs/require.js" data-main="js/main.js"></script>
## main.js
RequireJS 需要配置config
require.config({
//基本路径
baseUrl : 'js/',
//标识名称与路径的映射
paths : {
'模块1' : 'modules/模块1', //配置中引入模块 不可以写后缀
'模块2' : 'modules/模块2',
'angular' : 'libs/angular',
'angular-messages' : 'libs/angular-messages'
},
//非AMD的模块
shim : {
'angular' : {
exports : 'angular'
},
'angular-messages' : {
exports : 'angular-messages',
deps : ['angular']
}
}
})
//配置中引入模块 不能写后缀.js 会报错
CMD
- 说明
Common Module Definition(通用模块定义)
专门用于浏览器端, 模块的加载是异步的
模块使用时才会加载执行(依赖于 Sea.js)
- 语法
## 暴露模块
//定义有依赖的模块
define(function(require, exports, module){
//引入依赖模块(同步)
var module2 = require('./module2')
//引入依赖模块(异步)
require.async('./module3', function (m3) {
})
//暴露模块
exports.xxx = value
})
## 引入模块
define(function (require) {
var m1 = require('./module1')
var m4 = require('./module4')
m1.show()
m4.show()
})
- 实现
依赖于 Sea.js
- 总结
区别:
AMD 是 RequireJS 在推广过程中对模块定义的规范化产出。
CMD 是 SeaJS 在推广过程中对模块定义的规范化产出。
1. 对于依赖的模块,AMD 是提前执行,CMD 是延迟执行。
不过 RequireJS 从 2.0 开始,也改成可以延迟执行(根据写法不同,处理方式不同)。
CMD 推崇 as lazy as possible.
2. CMD 推崇依赖就近,AMD 推崇依赖前置。
看代码:
// CMD
define(function(require, exports, module) {
var a = require('./a')
a.doSomething()
// 此处略去 100 行
var b = require('./b') // 依赖可以就近书写 (用的时候再去引入)
b.doSomething()
// ...
})
// AMD 默认推荐的是
define(['./a', './b'], function(a, b) {
// 依赖必须一开始就写好
a.doSomething()
// 此处略去 100 行
b.doSomething()
...})
ESM(ES6 Module)
- 说明
用于浏览器端
依赖模块需要编译打包处理
- 语法
## 暴露模块
export
export default
## 导入模块
import { } form './xx/xx' //export
import module from 'module' //export default
- 实现
1. 安装babel-cli, babel-preset-es2015和browserify
* npm install babel-cli browserify -g
* npm install babel-preset-es2015 --save-dev
* preset 预设(将es6转换成es5的所有插件打包)
2. 定义.babelrc文件
{
"presets": ["es2015"]
}
使用Babel将ES6编译为ES5代码 :
babel example.js -o compiled.js 单个文件
babel js/src -d js/lib 整个文件夹
使用Browserify编译打包js : browserify js/src/app.js -o js/dist/bundle.js
html引入最后的文件才可以运行(其实这里就是webpack的作用)
- 问题
问题: 所有浏览器还不能直接识别ES6模块化的语法
解决:
* 使用Babel将ES6--->ES5(使用了CommonJS) ----浏览器还不能直接支行
* 使用Browserify--->打包处理----浏览器可以运行
总结
到此,模块化规范简单介绍完毕,你会发现你缺少了一个自动化构建工具,不然任意修改js就需要手动打包。
猪脚登场webpack———一个实现了 CommonJS 和 ES6module 规范的自动化编译工具
参考文档
仅作为自己方便回顾,侵删
AMD 和 CMD 的区别有哪些?
资料整理来自这里