前端思维导图
2023-03-27 17:22:39 1 举报
AI智能生成
前端导图
作者其他创作
大纲/内容
性能优化
输入 URL
DNS获取IP地址
建立TCP连接
建立HTTPS连接
建立HTTP连接
后端返回内容
页面渲染
网络层面
通过link标签的dns-prefetch属性对项目中其他域名去预解析
CSS 雪碧图(合并)、base64(file-loader 转换)、选择webp、图片懒加载、预加载
代码压缩
路由懒加载
代码层面
组件合理拆分
利用 Template 的 block tree 特性
for 循环唯一 key
合理使用computed(lazy watch)
重绘、回流
class 代替频繁操作 style
批量操作dom
尽量使用 transform
缓存层面
协商缓存 (304)
ETag
Last-Modified
强缓存(200 from cache)
Cache-Control
Expires
from memory cache(不请求网络资源,资源在内存当中,一般脚本、字体、图片会存在内存当中)
from disk cache(不请求网络资源,在磁盘当中,一般非脚本会存在内存当中,如css等)
渲染层面
HTML 渲染过程特点
顺序执行、并发加载
CSS阻塞
css haed 中阻塞页面的渲染(保证有样式,也就是说页面的渲染会等到 css加载完成)
css 阻塞js执行
css 不阻塞js加载
js 阻塞
直接引入的 js 会阻塞页面的渲染
js 不阻塞资源的加载
js 顺序执行,阻塞后续js逻辑的执行
依赖关系
页面渲染依赖css加载
js的执行顺序有依赖关系
js 逻辑对dom节点有依赖关系
js 引入方式
直接引入(阻塞页面渲染)
defer(不阻塞页面渲染,按顺序执行)
async(不阻塞页面渲染,不按顺序执行)
异步动态引入js
策略
css 样式置顶
link 代替 @import
js 脚本置底
合理使用 js 的异步加载能力
打包层面
优化解析时间
thread-loader(创建 worker pool 来多进程地对每个loader处理)
happypack 多进程处理 loader
利用打包缓存
cache-loader
hardSourceWebpackPlugin
优化压缩时间
terser-webpack-plugin 启动多进程压缩优化代码
缩小搜索时间
利用 loader 的test、include、exclude 等配置项
利用 resolve 的 alias、modules、extensions 等配置项
减少请求次数
url-loader 对小图片进行 base64 转换
雪碧图
减少包体积
使用 externals 来避免第三方包打入到 verdor 中
使用懒加载(路由懒加载、组件懒加载)
tree shaking (lodash-es 包)
scope hoisting 作用域提升
html、css、js 压缩
利用浏览器缓存
optimization.splitChunks
miniCss 工具来提取 css 并配置 content-hash
SSR
工具指标
lighthouse
FCP 首次渲染时间
TTI 页面可以开始交互的时间
LCP 页面中最大的图片或文本块渲染的时间
工程化
webpack
定位:静态模块打包工具
工作流程
初始化阶段
初始化参数:从配置文件、shell参数、配置对象中读取,与默认配置合并生成最终参数
初始化编译器对象:用上一步参数创建 Compiler 对象
初始化编译环境:包括注入内置插件、注册各种模块工厂、初始化 RuleSet 集合、加载配置的插件等
开始编译:执行 compiler 的 run 方法
确定入口:根据 entry 找出所有的入口文件,调用 compilituon.addEntry 将入口文件转换为 dependence 对象
构建阶段
编译模块:根据 entry 对应的 dependence 创建 module 对象,loaders 逐个执行,将对应文件转译为有效模块。
并调用 JS 解释器将其转化为 AST 对象,从中找到该模块依赖的模块,再递归处理。
并调用 JS 解释器将其转化为 AST 对象,从中找到该模块依赖的模块,再递归处理。
完成模块编译:通过模块间的依赖关系,得到依赖关系图
生成阶段
输出资源:根据入口和模块之间的依赖关系,组装一个个包含多个模块的 chunk,再把每个 chunk 转换成一个单独的文件
在生成好输出内容后,根据配置的输出路径和文件名,把文件内容写入到文件系统
自定义 plugin
在执行new Plugin() 的时候执行插件原型上的 apply 方法
通过进行钩子函数的监听来执行不同的操作(compiler.hooks.xxxx.tap)
场景:在 build 的时候生成一个 md 文件,统计打包的文件名和数量
自定义 loader
场景:自定义 md-loader,渲染出 md 文件
名词概念
module(源码中的文件)
chunk(webpack构建时的文件)
bundle(输出后的文件)
entry(编译入口,webpack 编译的入口)
compiler(编译管理器,webpack启动后会创建一个 compiler 对象,该对象一直存在)
plugin(打包优化,资源管理,注入环境变量等)
loader(loader 用于转换某些类型的模块)
tapable(是 webpack 用来创建钩子的库,为 webpack 提供了插件接口的支柱)
hash(所有文件哈希值相同,只要改变内容跟之前的不一致,所有哈希值都改变,没有做到缓存意义)
chunkhash(同一个模块,就算将js和css分离,其哈希值也是相同的,修改一处,js和css哈希值都会变,同hash,没有做到缓存意义)
contenthash(只要文件内容不一样,产生的哈希值就不一样,抽离出的CSS文件可以使用)
模块联邦
场景:微前端的公共模块拆分
vite(bundle less)
启动速度
对于依赖,使用 Esbuild 进行预构建
对于源码,利用浏览器ESM特性,让浏览器接管打包程序的部分工作,Vite 只需要在浏览器请求源码的时候进行转换输出
更新速度
对于源码模块会利用协商缓存
对于依赖模块会利用强缓存
webpack 的HMR还需要重新构建并重载页面,而 vite 因为没有经过 bundle,所以可以只替换编辑的文件即可
为什么生产环境仍然需要打包(默认 rollup 进行生产构建,也是基于 ESM)
嵌套导入带来额外的网络往返
打包可以带来 tree-shaking、懒加载、chunk 分割
缺点
生态不如webpack
生产环境使用 rollup,可能会开发环境、生产环境不同
微前端
定位
技术栈无关
独立开发、独立部署
增量升级
独立运行时
方案选择
iframe
技术成熟
支持页面嵌入
自带沙箱隔离、独立运行
通讯机制孱弱
应用的加载、渲染、缓存可控性不足
页面可以不同域名带来鉴权问题
web component
支持自定义元素
支持 shadow dom
支持模板 template 和插槽 slot
接入时候需要对原项目进行重写
兼容性不好
Single SPA及qiankun
EMP
利用 webpack5 的模块联邦进行模块共享
接入成本高、兼容性差
qiankun
子应用需要支持 script、common.js、AMD 形式引用
webpack 的 output 中,libraryTarget: 'umd'
子应用需要支持CORS
webpack 的 devServer 中,增加 headers: { 'Access-Control-Allow-Origin': '*' }
子应用需要增加声明周期钩子函数供主应用调用
增加 bootstrap、mount、unmount 等钩子函数,并在 mount 中调用 render
防止多个子应用的全局变量冲突
webpack 的 output 中,修改 jsonpFunction 配置一个自定义的名称(webpack5 中已移除)
JS隔离
快照沙箱:性能差,适用于老旧浏览器,只能单实例,即一个页面只能有一个子应用
代理沙箱:可以支持单实例、多实例,利用 proxy 实现
CSS隔离
css modules
shadow dom
minicss
postcss-selector-namespace
css in js
通信
CustomEvent
props
计算机相关
线程和进程
进程是资源分配的最小单位
线程是CPU调度的最小单位
进程可以比作“火车”,线程可以比较“车厢”,即一个进程可以有多个线程,线程必须在进程中运行。
数据结构
哈希表
散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构
Javascript 通常用 Map 结构进行代替,查询时间复杂度为 O(1)
数组
数组(Array)是有序的元素序列。
访问的时间复杂度O(1)、搜索的时间复杂度O(n)
二叉树
时间复杂度O(logn)
JS基础
异步
callback
promise
设计 scheduler
设计 retry
event loop
手写 promise
手写 promise.all
手写 promise.race
promisify
generator
co函数
thunk 函数
async await
继承
原型链继承
Child.prototype = new Parent()
所有属性会被实例共享,所以引用类型时候会有问题
创建子类实例时,不能传参
构造函数继承(经典继承)
在Child类中 使用call或apply来调用Parent类
避免了引用类型被所有实例共享
可以通过子类向父类传参
不能访问父类的原型上方法和属性
组合继承
组合继承是原型链继承和经典继承的双剑合璧。
父类的构造函数会执行两次
原型式继承
和原型链继承一样,引用类型的属性会被所有的实例共享
寄生式继承
和借用构造函数(经典继承)一样,每次创建对象都会把方法创建一遍
寄生组合继承
理想继承
class 继承
必须要调用 super(),才能继承父类
编译成一个IFFE自执行函数,内部通过 _createClass 对 class 里的方法进行循环处理,其内部通过 Object.defineProperty 将方法挂载到原型上
手写
手写 call
手写 apply
手写 bind
手写 new
手写防抖
手写节流
手写 instanceof
打乱顺序
shuffle
sort(小于10时是插入排序,否则为快排)
框架
Vue3
Feature
源码优化
Monorepo (更好的代码结构,社区的二次开发)
Typescript (开发维护)
性能优化
包体积(移除API、Tree-shaking)
数据劫持 (Proxy 代替 Object.defineProperty)
编译优化
Block-Tree
API
Composition
优化逻辑组织
优化逻辑复用
原理
编译阶段(Template => VNode)
分类
Runtime + Compiler
Runtime only (借助 vue-loader)
过程
parse (Template => AST)
和Vue2不同之处:多了一个虚拟根节点,从而支持 Fragment
transform (AST 转换)
创建 transform 上下文
遍历 AST 节点(核心:处理各种指令、表达式等,并给每种节点打上标签)
静态提升 (每次 render 的时候可以重用之前的 VNode)
创建根代码生成节点
generate (AST => VNode)
VNode => DOM (组件初始化的过程)
响应式
Vue2
Vue3
对比React(或者问:为什么Vue不需要fiber架构)
在Vue1中,因为依赖收集了全部数据的watcher,导致项目庞大时候的性能问题
在Vue2中,依赖收集仅仅收集了组件级别的render watcher,和用户设置的 user wacher(computed、watch),而组件内部的更新,是通过引入的虚拟dom的diff来处理,这样就极大减小了 wacher 的监听数量
React 中在 React16 之前通过 diff 对整个dom数进行diff比较,导致页面卡顿
React 16之后采用 fiber 机制来解决页面卡顿问题
diff (组件更新的过程中,新旧节点都是 vnode 数组时)
Vue3 (利用编译阶段的BlockTree,来减少比对数量)
同步头部节点
同步尾部节点
处理剩余节点
添加新增节点
删除多余节点
处理未知子序列
寻找最长递增子序列
Vue2
旧的首节点和新的首节点
旧的尾节点和新的尾节点
旧的首节点和新的尾节点
旧的尾节点和新的首节点
零碎知识点
父子通信
Provide/Inject
props/$emit
Vuex 等类状态管理
$parent/$children
自定义广播
eventBus
$ref
teleport
组件的API形式调用
v-model 语法糖(props为 value,emit 为 input)
.sync 语法糖
nextTick
keep-alive(LRU)
观察者模式、发布-订阅模式
插件
Vue-Router
Vuex
React
架构
Scheduler(调度器)—— 调度任务的优先级,高优任务优先进入Reconciler
时间切片(本质还是模拟 requestIdleCallback)
优先级划分:根据用户对交互的预期顺序为交互产生的状态更新赋予不同的优先级
Reconciler(协调器)—— 负责找出变化的组件(为变化的虚拟DOM打上标记,
当所有组件都完成Reconciler的工作,才会统一交给 Renderer)
当所有组件都完成Reconciler的工作,才会统一交给 Renderer)
React15 中递归处理虚拟DOM
React16 可以中断的循环处理
通过调用 shouldYield 判断当前是否还有剩余时间
Fiber
定义:React 内部实现的一套状态更新机制。支持任务不同优先级,
可中断与恢复,并且恢复后可以复用之前的中间状态
可中断与恢复,并且恢复后可以复用之前的中间状态
架构层面:Fiber 调和器
数据结构:Fiber 结构 类似于链表结构
return (父节点)
child (子节点)
sibling (兄弟节点)
更新任务单元:Fiber 保存了本次更新中该组件改变的状态、要执行的工作
工作原理:双缓存
与JSX 的区别
diff
预设条件
同级比较
不同的类型元素直接替换更新,不比较内部
设置 key 来更大化复用
递增法 —— 找递增子序列 O(m*n)
key 与 index 构成一个Map O(n)
Renderer(渲染器)—— 负责将变化的组件渲染到页面上
API
setState
同步or异步
只有在生命周期函数中、React的合成事件中,才会触发令 isBatchingUpdate 为 true
useEffect 和 useLayoutEffect
修改 DOM ,改变布局就用 useLayoutEffect ,其他情况就用 useEffect 。
React.forwardRef
事件系统
合成事件(绑定的事件会冒泡到document处,然后交由专门的处理函数处理)
抹平各浏览器间的兼容问题
跨平台
性能(相当于事件委托)
更新机制
触发时机:this.setState、this.forceUpdate、ReactDOM.render
浏览器
页面至少有4个进程
浏览器进程
渲染进程
该域名下的所有页面共享一个
GPU进程
网络进程
插件进程
网络协议
网络层 IP 协议 (IP头:传送到目标主机)
传输层 TCP/UDP 协议(传送到目标应用程序)
TCP头:数据可靠、具有重发机制
三次握手
四次挥手
UDP头:快、不可靠、无重发机制
应用层 HTTP协议
http1.1
连接持久化,减少TCP的连接和断开次数
每个域名下可同时维护6个TCP持久连接
Cookie 和 安全机制
队头阻塞
慢启动
多条TCP连接竞争带宽
https(解决中间人攻击)
在TCP和HTTP之间增加SSL/TLS安全层
作用
对发起HTTP请求的数据进行加密
对接收的HTTP数据进行解密操作
采用非对称+对称加密
浏览器向服务器发送对称加密套件列表、非对称加密套件列表、客户端随机数
服务器向浏览器发送对称加密套件、非对称加密套件、服务端随机数、公钥
浏览器生成新的随机数,并用公钥加密发送给服务器
服务器用自己的私钥对接收的随机数进行解密,并返回确认消息
至此,浏览器和服务器端都有了三个随机数,就可以以此生成对称秘钥
黑客可以在用户计算机上安装假数字证书
存在DNS劫持安全问题(服务器端发送给浏览器端的公钥换成数字证书)
数字证书的申请
网站向 CA 机构提交公钥、公司、站点等信息并等待认证
认证成功后,CA会向网站下发数字证书,包含公钥及公司相关信息
数字证书的认证
验证签名是否可信
浏览器和系统都会内置一些根证书,当浏览器收到服务端发送的数字证书会查看证书链里是否包含根证书,如果没找到,则通过中间证书向上继续找
验证信息是否匹配
比如 证书中包含的域名必须与客户端请求的域名一致
验证证书是否被篡改
浏览器读取证书中相关的明文信息,采用 CA 签名时相同的 Hash 函数来计算并得到信息摘要 A;
利用对应 CA 的公钥解密签名数据,得到信息摘要 B;
对比信息摘要 A 和信息摘要 B,如果一致,则可以确认证书是合法的;
性能短板
SSL/TLS 的会话重用
使用轻量级加密算法
服务器配置专门的加密芯片
CDN加速,相当于负载均衡了
HTTP2来多路复用等特性
http2
每个域名只使用一个TCP长连接,减少慢启动
多路复用(将请求分成一帧一帧的数据去传输)
头部压缩
TCP 的头部阻塞
Server Push
和 web socket 协议的区别
TCP/IP 四层模型
OSI 七层模型
应用层(HTTP、TFTP, FTP, NFS, WAIS、SMTP)主要是终端应用,比如说是FTP(各种文件下载),web浏览器,QQ
表示层(Telnet, Rlogin, SNMP, Gopher)主要是对接收的数据进行解释 加密与解密压缩与解压缩等
会话层(SMTP, DNS)通过传输层(端口号:传输端口与接受端口)建立数据传送的通路
传输层(UDP/TCP)定义了一些传输数据的协议和端口号(www端口 80等)
网络层(IP, ICMP, ARP, RARP, AKP, UUCP)主要从下层接受到的数据进行IP地址(192.168.0.1)的封装与解封装,主要设备是路由器
数据链路层(FDDI, Ethernet, Arpanet, PDN, SLIP, PPP)将物理层接受的数据进行MAC地址(网卡地址)的封装与解除封装,主要设备是交换机
物理层(IEEE 802.1A, IEEE 802.2到IEEE 802.11)定义物理设备的标准,包括网线、wifi、光缆等
安全
同源策略(协议、域名、端口都相同)
CSP,满足安全地引入第三方资源,防止XSS攻击
CORS,满足跨域请求
postMessage,满足跨文档通信
XSS 跨站脚本攻击
服务器对输入脚本进行过滤或者转码
充分利用CSP
利用 HttpOnly 属性
CSRF 跨站资源伪造(不需要将恶意代码注入用户的页面,利用服务器的漏洞和用户的登录状态来实施攻击)
利用 SameSite 属性
利用 Origin 或者 Referer 属性
CSRF Token
垃圾回收机制
栈内存中数据
利用 ESP(当前执行状态的指针) 的下移,来销毁栈内存中的数据
堆内存中数据(根据代际假说分成两类)
大部分对象在内存中存在的时间很短,简单来说,就是很多对象一经分配内存,很快就变得不可访问;(新生代)
副垃圾回收器
不死的对象,会活得更久(旧生代)
主垃圾回收器
算法
栈
队列
链表
删除链表中节点
判断是否是环形链表
链表反转
链表两数相加
删除重复链表
集合
字典
树
BFS(栈)
DFS(递归)
二叉树
前序(根-左-右)
中序(左-根-右)
后序(左-右-根)
排序
冒泡排序:双层循环不断前后对比
复杂度:O(n^2)
复杂度:O(n^2)
选择排序:双层循环每次找到最小的
复杂度:O(n^2)
复杂度:O(n^2)
插入排序:双层循环,从索引1的数字依次向前比较
复杂度:O(n^2)
复杂度:O(n^2)
快速排序:找到一个基准数,进行分区操作,再递归依次处理下去
复杂度:分区O(n) * 递归O(logN) = O(n * logN)
复杂度:分区O(n) * 递归O(logN) = O(n * logN)
二分法
分治
动态规划
回溯
LeetCode HOT100
滑动模块
无重复字符的最长子串
双指针
最长回文子串
三数之和等于0(排序后双指针,考虑重复问题)
栈
寻找两个正序数组的中位数(拆解为两个数组的合并)
有效的括号
链表
链表合并
删除链表的倒数第N个节点(链表反转+删除链表某个节点)
BFS、DFS
括号的生成
0 条评论
下一页