客户端容器-渲染进程
渲染进程-资源加载
1.收到主进程的消息后,开始加载HTML文档
2.还需要加载子资源,比如一些图片,CSS样式文件以及JavaScript脚本
渲染进程-构建渲染树
1.构建DOM树,将HTML文本转化为浏览器能够理解的结构
2.构建CSSOM树,浏览器同样不认识CSS,需要将CSS转化为可理解的CSSOM。和第一节的笔记相对应。
渲染进程-页面布局
1.根据渲染树计算每个节点的位置和大小
2.在浏览器页面区域绘制元素边框
3.遍历渲染树,将元素以盒模型的形式写入文档流
渲染进程-页面绘制
1.构建图层:为特定的节点生成专用图层
2.绘制图层:一个图层分成很多绘制指令,然后将这些指令按顺序组成一个绘制列表,交给合成线程
3.合成线程接收指令生成图块
4.栅格线程将图块进行栅格化
5.展示在屏幕上
这里引出首屏优化: 1.压缩、分包、删除无用代码
2.静态资源分离
3.JS脚本非阻塞加载
4.缓存策略
5.SSR
6.预置loading、骨架屏
渲染优化
1.GPU加速
2.减少回流,重绘
3.离屏渲染
4.懒加载
JS优化
1.防止内存泄露
2.循环尽早break
3.合理使用闭包
4.减少 Dom 访问
5.防抖、节流
6.Web Workers
下面贴一段代码有关JS引擎与渲染引擎桥接通信的,可以简单了解一下:
interface CallArgs {
callId: string // 调用Id,唯一标识
module: string // 调用模块
method: string // 调用方法
data: any // 参数
}
const Callbacks = {} // 存放回调函数 callId 为key
function applyNative = (payload:CallArgs, callback: Function) => {
const callId = prefix + callTime++
Callbacks[callId] = callback
const Args0: CallArgs = {
callId: callId,
module: payload.module || 'layout',
method: payload.method || 'randomSize',
data: payload.data,
}
if (IOS) {
return window.webkitURL.messageHandler.postMessage(JSON.stringify(Args0))
} else {
// Android 对 window 上约定的对象进行拦截
return window.AndroidBridge(JSON.stringify(Args0))
}
}
interface ResponsArgs {
responseId: string // 回调Id,与 callId 对应
errCode: number
errMsg?: string
data: unknown
}
// native端调用 webview, 参数都经过序列化
const applyWebview = (res: string) => {
const response = JSON.parse(res) as ResponseArgs
const { responseId } = response
// 从 Callback 找到对应的回调处理方法
if (type of Callbacks[responseId] === 'function') {
Callbacks[responseId](response)
// 回调后删除该次回调函数
delete Callbacks[responseId]
}
}
window.JSBridge = {
applyNative,
applyWebview // 挂载在window上,供native调用
}