模块化的意义及学习路径:
意义
模块化是前端重要开发范式,前端项目日益复杂,项目需要花大量时间管理。
模块化将复杂代码依据功能不同划分为不同的模块,降低维护成本,提高开发效率。
学习路径
- 模块化演变过程介绍(了解历史、价值、及解决的问题)
- 前端模块化标准,规范
- 常用模块化打包工具
- 结合案例应用模块化打包工具
- 介绍常用模块化打包工具的优化技巧提高使用
演变过程
1、文件划分方式
每个功能、状态数据不同的文件,约定每个文件为不同模块,使用模块即使用JavaScript通过src引用,使用全局成员,例全局变量或全局对象
缺点:
- 污染全局作用域
模块内的所有成员可在外部任意更改、任意访问 - 命名冲突问题
- 无法管理模块依赖关系
早期模块化完全依靠约定,项目体量变大则不行
2、命名空间方式
每个文件向外部暴露一个全局对象,所有的对应的方法全部挂载在全局对象上。
文件目录大概如下:
——demo
————module-a.js
————module-b.js
————index.html
//module-a.js
var moudleA = {
name: 'module-a',
method1: function (params) {
console.log('moduleA - mthod1');
},
method2: function (params) {
console.log('moduleA - mthod2');
}
};
//module-b.js
var moudleB = {
name: 'module-b',
method1: function (params) {
console.log('moduleB-method1');
},
method2: function (params) {
console.log('moduleB-method2');
}
};
//index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<h1>模块化演变(第二阶段)</h1>
<h2>每个模块只暴露一个全局对象,所有模块成员都挂载到这个对象中</h2>
<script src="./module-a.js"></script>
<script src="./module-b.js"></script>
<script>
moudleB.method1();
console.log(moudleA.name);
moudleA.name = 'changeNAME'; //在模块外部可以随意修改内部变量
console.log(moudleA.name);
</script>
</body>
</html>
模块内给模块内每个成员增加了命名空间的方式,比第一种方法相比较优点是避免了变量名冲突,不过依旧存在缺点:
- 仍然没有私有空间,内部成员在外部可随意访问、随意修改。
- 各个模块直接的依赖关系不清晰
3、IIFE 立即执行函数
立即执行函数给模块提供私有空间,每个成员放入函数的私有空间中,需要暴露给外部的成员挂载在全局对象上实现。
实现了私有成员概念,私有成员模块只能在模块内部通过闭包的方式来实现,在外部是无法访问,实现了私有空间的安全。
——demo
————module-c.js
————index.html
//module-c
!(function (params) {
var name = 'IFEE';
function method1(params) {
console.log('IFEE method1');
}
function method2(params) {
console.log(name + 'IFEE method2');
}
window.moduleC = {
method1: method1,
method2: method2
};
})();
//index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<p>测试module-c引入Jquery模块改变p标签颜色</p>
<script src="./module-c.js"></script>
<script src="./module-d.js"></script>
<script
src="https://code.jquery.com/jquery-3.6.0.min.js"
integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4="
crossorigin="anonymous"
></script>
<script>
console.log(moduleC.name); // moduleC is not defined。无法直接使用模块c中name值
moduleC.method1(); //IFEE method1
</script>
</body>
</html>
- 这种方式优势在于有自己的私有空间,模块内数据不会直接被外部随意使用,需要提供给外部使用的数据通过闭包形式提供给外部使用。
- 可以清晰地表明模块间依赖关系;立即执行函数可传入参数,在立即执行时传入需要依赖的模块,例如下方代码:
模块c需要依赖于jquery模块,可以传入jquery。下方代码为伪代码,具体实现还是需要用到下面的模块化知识。
//module-c.js
!(function ($) {
var name = 'IFEE';
function method1(params) {
console.log('IFEE method1');
$('p').css({ color: '#ff0011', background: 'blue' });
}
function method2(params) {
console.log(name + 'IFEE method2');
}
window.moduleC = {
method1: method1,
method2: method2
};
})(JQuery);