工程化关键技术
# 前端工程化关键技术
# 前端模块化的进化过程
第一阶段:全局function模式,将不同的功能封装成函数。但是函数在全局作用域下,容易引发命名冲突。
第二阶段:全局namespace模式,通过对象封装模块。在window下封装对象,如给window添加属性对象window.__Module,将函数放入这个对象。但是外部能够对内部数据进行修改。
第三阶段:IIFE(Immediately-invoked function expression)模式,通过自执行函数创建闭包。但是无法解决模块间相互依赖问题。
(function(global) {
var a = 1;
function api() {
return {
code: 0,
data: {
a,
b: 2,
},
};
}
function handle(data, key) {
return data .data[key];
}
function sum(a, b) {
return a + b;
}
global.__Module_API = {
api,
handle,
sum,
};
})(window)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
第四阶段,IIFE模式增强,支持传入自定义依赖。缺陷:多依赖传入时,代码阅读困难。无法支持大规模的模块化开发。无特定语法支持,代码简陋。
(function(global,moduleAPI){
function sum(a,b){
return a + b
}
global.__Module = {
api:moduleAPI.api,
handle:moduleAPI.handle,
sum,
}
})(window,window.__Module_API)
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# CommonJS、AMD、CMD、ES Module 规范
# CommonJS规范
- Node.js默认模块化规范,每个文件就是一个模块,有自己的作用域
- Node中CJS模块加载采用同步加载方式
- 通过 require 加载模块,通过 exports 或 module.exports 输出模块
# CommonJS特性
- 所有代码都运行在模块作用域,不会污染全局作用域。
- 模块可以多次加载,第一次加载时会运行模块,模块输出结果会被缓存,再次加载时,会从缓存结果中直接读取模块输出结果。
- 模块加载的顺序,按照其在代码中出现的顺序。
- 模块输出的值是值的拷贝,类似IIFE方案中的内部变量。
# CommonJS原理
# CommonJS模块打包
- 安装browserify: npm install browserify -g
- 模块打包命令: browserify module_test/cis/entry.js -o dist/bundle.js
- 注意,当存在多个模块时,每个模块都需要单独打包
在浏览器中使用CommonJS规范需要进行打包才能使用,直接将采用了CommonJS规范的JS代码作为Script标签的脚本插入到html中会提示没有require方法。
# browserify打包原理
- 本质还是通过自执行函数实现模块化
- 将每个模块编号,存入一个对象,每个模块标记依赖模块
- 实现了require方法,核心是通过call方法调用模块,并传入require.module、exports方法或对象,通过module存储模块信息,通过exports存储模块输出信息
# AMD规范介绍
- 规范采用非同步加载模块,允许指定回调函数
- Node模块通常都位于本地,加载速度快,所以适用于同步加载
- 浏览器环境下,模块需要请求获取,所以适用于异步加载
- require.js是AMD的一个具体实现库
# CMD规范介绍
- CMD整合了CommonJS和AMD的优点,模块加载是异步的
- CMD专门用于浏览器端,sea.js是CMD规范的一个实现
- AMD和CMD最大的问题是没有通过语法升级解决模块化
# ESModule规范介绍
- ESModule设计理念是希望在编译时就确定模块依赖关系及输入输出
- CommonJS和AMD必须在运行时才能确定依赖和输入、输出
- ESM通过import 加载模块,通过export 输出模块
# CommonJS和ESModule规范对比
- CommonJS模块输出的是值的拷贝,ES6模块输出的是值的引用
- CommonJS 模块是运行时加载,ES6 模块是编译时输出接口
- CommonJs 是单个值导出,ES6 Module可以导出多个
- CommonJS模块为同步加载,ES6 Module支持异步加载
- CommonJS的this是当前模块,ES6 Module的this是undefined
- CommonJS和ES6 Module的语法不同
# 脚本和模块对比
- 模块具备更高的开发效率(可读性强、复用高效,但是模块文件多,加载速度慢)
- 脚本具有更高的页面性能(可以都写在一个文件中加载速度快)
- 模块在浏览器中运行会存在兼容性问题,要特别注意
# 浏览器模块化的局限
- 缺乏模块管理能力,模块分散在各个项目中
- 性能加载慢,无法大型项目中直接使用
- 这两个问题是npm和webpack核心解决的问题
# npm
# npm原理分析
# npm原理总结
- npm init创建模块,npm install安装模块,npm publish发布模块
- npm link本地开发,npm config调整配置,npm run调用scripts
- npm规范: package.json管理模块信息,node_modules保存依赖
# npm的局限性
- npm只能解决模块的高效管理和获取问题
- npm无法解决加载性能问题
- 模块化发明后,制约其广泛应用的因素就是性能问题
# webpack的原理
- 最初的webpack核心解决的问题就是代码合并与拆分
- webpack的核心理念是将资源都视为模块,统一进行打包和处理
- webpack提供了loader和plugins完成功能扩展
编辑 (opens new window)