了解前端模块化系列内容:
三、了解前端模块化系列(1)——模块化的理解
三、了解前端模块化系列(2)——模块化规范-CommonJS
三、了解前端模块化系列(3)——模块化规范-AMD
三、了解前端模块化系列(4)——模块化规范-CMD & ES6
三、了解前端模块化系列(5)——模块化规范-UMD & 总结(CommonJS AMD CMD ES6 UMD)
一、目标
-
前端模块化发展历程
-
掌握现代前端开发模块化的实现及实战
二、模块化的理解
-
模块化规范: JS 方面用来管理 web2.0 时代广泛应用 Ajax 技术、jQuery 等前端库而日益膨胀的前端代码。
-
已发展十余年的模块化,不同工具和轮子层出不穷,主要解决了:
- 外部模块管理;
- 内部模块组织;
- 模块源码&目标代码 的 编译&转换;
-
工具框架的诞生时间:
生态 诞生时间(年) Node.js 2009 NPM 2010 requireJS(AMD) 2010 seaJS(CMD) 2011 browserify 2011 webpack 2012 grunt 2012 gulp 2013 react 2013 vue 2014 angular 2016 redux 2015 vite 2020 snowpack 2020
2.1 什么是模块
2.2 模块化的进化过程
2.2.1 全局 function 模式
举例:
function m1() {
//...
}
function m2() {
//...
}
2.2.2 namespace 模式
举例:
let myModule = {
data: 'www.baidu.com',
foo() {
console.log(`foo() ${this.data}`)
},
bar() {
console.log(`bar() ${this.data}`)
}
}
myModule.data = 'other data' //能直接修改模块内部的数据
myModule.foo() // foo() other data
2.2.3 IIFE 模式
匿名函数自调用(闭包)
- 作用:
① 数据私有
② 外部只能通过暴露方法操作 - 编码:
① 函数内部封装:数据&行为
② window添加 myModule属性,向外暴露接口 foo,bar - bug:
当前模块依赖另一个模块,怎么办?
举例:
index.html
<script type="text/javascript" src="module.js"></script>
<script type="text/javascript">
myModule.foo() // 【1.作用】——②外部只能通过暴露方法操作
myModule.bar() // 【1.作用】——②外部只能通过暴露方法操作
console.log(myModule.data) //undefined 不能访问模块内部数据
myModule.data = 'xxxx' //不是修改的模块内部的data
myModule.foo() //没有改变
</script>
module.js
;(function (window) {
let data = 'www.xianzao.com' // 【1.作用】——①数据私有
//操作数据的函数
function foo() {
//用于暴露有函数
console.log(`foo() ${data}`)
}
function bar() {
//用于暴露有函数
console.log(`bar() ${data}`) // 【2.编码】——①函数内部封装:**数据**&行为
otherFun() //内部调用
}
function otherFun() {
//内部私有的函数
console.log('otherFun()') // 【2.编码】——①函数内部封装:数据&**行为**
}
//暴露行为
window.myModule = { foo, bar } //ES6写法 // 【2.编码】——②**window**添加myModule**属性**,向外**暴露接口** foo,bar
})(window)
// 【3.bug】——当前模块依赖另一个模块,怎么办?
结果:
foo() www.xianzao.com
bar() www.xianzao.com
otherFun()
undefined
foo() www.xianzao.com
2.2.4 IIFE 模式增强
现代模块实现的基石。
- jQuery 页面背景改红
- 先引入 jQuery 库
- 库当作参数传入
- 保证模块的独立性
- 模块之间依赖关系变得明显
举例:
module.js
;(function (window, $) {
let data = 'www.baidu.com'
//操作数据的函数
function foo() {
//用于暴露有函数
console.log(`foo() ${data}`)
$('body').css('background', 'red') // 1. jQuery页面背景改红
}
function bar() {
//用于暴露有函数
console.log(`bar() ${data}`)
otherFun() //内部调用
}
function otherFun() {
//内部私有的函数
console.log('otherFun()')
}
//暴露行为
window.myModule = { foo, bar }
})(window, jQuery)
index.html
<!-- 引入的js必须有一定顺序 -->
<script type="text/javascript" src="jquery-1.10.1.js"></script> // 2. 先引入jQuery库
<script type="text/javascript" src="module.js"></script> // 3. 库当作参数传入
<script type="text/javascript">
myModule.foo()
</script>
// 4. 保证模块的独立性
// 5. 模块之间依赖关系变得明显
2.3 模块化的优点&缺点
- 优点
- 避免命名冲突(减少命名空间污染)
- 更好分离,按需加载
- 更高复用性
- 高可维护性
- 缺点——引入多个
<script>标签后:- 请求过多(多模块 -> 多请求)
- 依赖模糊(加载先后顺序出错)
- 难以维护(1+2=3)
- 解决缺点——通过模块化规范:
- common.js 规范
- AMD 规范
- ES6 规范
- CMD 规范