[ 前端与客户端容器 -3 | 青训营笔记 ]

68 阅读2分钟

客户端容器-渲染进程

渲染进程-资源加载

1.收到主进程的消息后,开始加载HTML文档

2.还需要加载子资源,比如一些图片,CSS样式文件以及JavaScript脚本

image-20230421151007688.png

渲染进程-构建渲染树

1.构建DOM树,将HTML文本转化为浏览器能够理解的结构

2.构建CSSOM树,浏览器同样不认识CSS,需要将CSS转化为可理解的CSSOM。和第一节的笔记相对应。

image-20230421151031038.png

渲染进程-页面布局

1.根据渲染树计算每个节点的位置和大小

2.在浏览器页面区域绘制元素边框

3.遍历渲染树,将元素以盒模型的形式写入文档流

image-20230421151202350.png

渲染进程-页面绘制

1.构建图层:为特定的节点生成专用图层

2.绘制图层:一个图层分成很多绘制指令,然后将这些指令按顺序组成一个绘制列表,交给合成线程

3.合成线程接收指令生成图块

4.栅格线程将图块进行栅格化

5.展示在屏幕上

image-20230421151327054.png

这里引出首屏优化: 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调用
}