客户端容器 | 青训营笔记

124 阅读7分钟

1 目标

  • 浏览器架构模式介绍
  • 渲染进程
  • Chrome运行原理
  • 跨端容器

2 浏览器架构

  • 单进程架构
    • 所有模块运行在同一个进程里,包含网络、插件、JavaScript运行环境等
  • 多进程架构
    • 主进程、网络进程、渲染进程、GPU进程、插件进程
  • 面向服务架构
    • 算是多进程架构的升级版。将原来的UI、数据库、文件、设备、网络等,作为一个独立的基础网络服务

image.png

2.1浏览器架构对比

image.png

2.2 任务管理器

  • (用Chrome演示)查看路径:【左上角三个点】→【更多工具】→【任务管理器】

任务管理器: image.png

由任务管理器可知,浏览器是一个多进程架构,多进程架构分工: image.png

2.3 QS

  • 为什么会有单进程架构?

    • 早期受到硬件限制,为了节约资源。
  • 面向服务架构是否会替代多进程架构?

    • 有可能会被替代。

3 渲染进程

  • 主线程(Main thread)
    • (下载资源、执行js、计算样式、进行布局、绘制合成)
  • 光栅线程(Raster thread)
  • 合成线程(Compositor thread)
  • 工作线程(Worker thread)

3.1 常见浏览器内核

image.png

3.2 渲染进程内部

渲染进程内部是多线程实现,主要负责页面渲染,脚本执行,事件处理,网络请求等。 image.png

  • 解释执行JS
  • XML解析生成渲染树,显示在屏幕
  • 桥接方式通信 image.png

3.3 多线程工作流程

  • 网络线程负责加载网页资源
  • JS引擎解析JS脚本并执行
  • JS解析引擎空闲时,渲染进程立即工作
  • 用户交互、定时器操作等产生回调函数放入任务队列中
  • 事件线程进行事件循环,将队列里的任务 取出交给JS引擎执行

image.png

笔试题

const now = Date.now();

setTimeout(() => {
    console.log("time10", Date.now() - now);
}, 10);

setTimeout(() => {
    console.log("time30", Date.now() - now);
}, 30);

while (true) {
    if (Date.now() - now >= 20) {
        break;
    }
}

console.log(Date.now() - now);
  • 结果
    • 函数 setTimeout 接受两个参数:待加入队列的消息和一个时间值(可选,默认为 0)。这个时间值代表了消息被实际加入到队列的最小延迟时间。如果队列中没有其它消息并且栈为空,在这段延迟时间过去之后,消息会被马上处理。但是,如果有其它消息,setTimeout 消息必须等待其它消息处理完。
    • 因此第二个参数仅仅表示最少延迟时间,而非确切的等待时间。

4 Chrome运行原理

image.png

  1. 输入处理

    • 用户URL框输入内容后,UI 线程会判断输入的时一个URL地址呢还是一个query查询条件;
    • 如果是URL,直接请求站点资源;
    • 如果是query,将输入发送给搜索引擎。 image.png
  2. 开始导航

    • 当用户按下回车,UI线程通知网络线程发起一个网络请求,来获取站点内容;
    • 请求过程中,tab页处于loading状态。
  3. 读取响应

    • 网络线程接受到HTTP响应后,先检查响应头的媒体类型(MIME type);
    • 如果响应主体是一个HTML文件,浏览器将内容交给渲染进程处理;
    • 如果拿到的是其他类型文件,比如zip、exe等,则交给下载管理器处理。 image.png
  4. 寻找渲染进程

    • 网络线程做完所有检查后,会告知主进程数据已经准备完毕,主进程确认后为这个站点寻找一个渲染进程;
    • 主进程通过IPC消息告知渲染进程去处理本次导航;
    • 渲染进程开始接受数据并告知主进程自己已开始处理,导航结束,进入文档加载阶段。 image.png
  5. 渲染进程-资源加载

    • 收到主进程的消息后,开始加载HTML文档;
    • 除此之外,还需要加载子资源,比如一些图片,CSS样式文件以及JavaScript脚本。

    image.png

  6. 渲染进程-构建渲染树

    • 构建DOM树,将HTML文本转化成浏览器能够理解的结构;
    • 构建CSSOM树,浏览器同样不认识CSS,需要将CSS代码转化为可理解的CSSOM;
    • 构建渲染树,渲染树是DOM树和CSSOM树的结合。 image.png
  7. 渲染进程-页面布局

    • 根据渲染树计算每个节点的位置和大小
    • 在浏览器页面区域绘制元素边框
    • 遍历渲染树,将元素以盒模型的形式写入文档流 image.png
  8. 渲染进程-页面绘制

    • 构建图层:为特定的节点生成专用图层
    • 绘制图层:一个图层分成很多绘制指令,然后将这些指令按顺序组成一个绘制列表,交给合成线程
    • 合成线程接收指令生成图块
    • 栅格线程将图块进行栅格化

image.png

前端性能performance

时间都花在哪里?什么情况下卡顿?

  • image.png

  • web性能常见指标:

    • First Paint 首次绘制(FP)
    • First contentful paint 首次内容绘制 (FCP)
    • Largest contentful paint 最大内容绘制 (LCP)
    • First input delay 首次输入延迟 (FID)
    • Time to Interactive 首次可交互时间 (TTI)
    • Total blocking time 总阻塞时间 (TBT)
    • Cumulative layout shift 累积布局偏移 (CLS)

首屏优化

  • 压缩、分包、删除无用代码
  • 静态资源分离
  • JS脚本非阻塞加载
  • 缓存策略
  • SSR
  • 预置loading、骨架屏

渲染优化

  • GPU加速:一般是利用css3
  • 减少回流、重绘
  • 离屏渲染
  • 懒加载

JS优化

  • 防止内存泄漏
  • 循环尽早break
  • 合理使用闭包
  • 减少DOM访问
  • 防抖、节流
  • Web Worker

5 跨端容器

为什么需要跨端

  • 开发成本、效率
  • 一致性体验
  • 前端开发生态 image.png

有哪些跨端方案

  • webview
  • 小程序
  • RN 、Weex
  • Lynx
  • Flutter

webview

  • Webview,即网页视图,用于加载网页Url,并展示其内容的控件。
    • 可以内嵌在移动端App内,实现前端混合开发,大多数混合框架都是基于Webview的二次开发:比如lonic、Cordova、uniapp。 image.png

优点

  • 一次开发,处处使用,学习成本低
  • 随时发布,即时更新,不用下载安装包
  • 移动设备性能不断提升,性能有保障
  • 通过JSBridge和原生系统交互,实现复杂功能
  1. Javascript调用Native:

    • API注入: Native获取Javascript环境上下文,对其挂载的对象或者方法进行拦截
    • 使用Webview URL Scheme跳转拦截
    • IOS上window.webkit.messageHandler直接通信
  2. Native调用Javascript:

    • 直接通过webview暴露的API执行JS代码
    • IOS方法:webview.stringByEvaluatingJavaScriptFromString
    • Android方法:webview.evaluateJavascript
  3. Webview 和 Native通信:

    1. JS环境中提供通信的JSBridge
    2. Native端提供SDK响应JSBridge发出的调用
    3. 前端和客户端分别实现对应功能模块 image.png

实现一个简单的JSBridge:

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{
        // 安卓对window上约定的对象进行拦截
        return window.AndroidBridge(JSON.stringify(Args0))
    }
}

interface ResponseArgs{
    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
    // 从Callbacks找到对应的回调处理方法
    if(typeof Callbacks[responseId]) === 'function'{
        Callbacks[responseId](response)
        // 回调后删除该次回调函数
        delete Callbacks[responseId]
    }
}

// 挂在在window上,供native直接调用
window.JSBridge = {
    applyNative,
    applyWebview
}

小程序

  • 常见小程序

    • 微信小程序
    • 支付宝小程序
    • 百度小程序
    • 小米直达号
  • 小程序架构:

    • 渲染层-webview
    • 双线程,多webview架构
    • 数据通信,Native转发 image.png

React Native / Weex

  • 原生组件渲染
  • React / Vue 框架
  • virtual dom
  • JSBridge

image.png

在安卓和IOS中展示是不一样的,因为底层还是调用的安卓或IOS的底层组件。

Lynx

  • 字节自研的一款跨端框架。(暂未开源,字节旗下使用较多)
    • Vue
    • JS Core / V8
    • JSBinding
    • Native UI / Skia image.png

Flutter

  • wideget
  • dart vm
  • skia图形库 image.png

通用原理

  • UI组件
  • 渲染引擎
  • 逻辑控制引擎
  • 通信桥梁
  • 底层API抹平表现差异 image.png

跨端方案对比

image.png

QS

  • 同样是基于webview渲染,为什么小程序体验比webview流畅?
    • 小程序会先把需要的资源下载下来,在使用的时候直接使用
    • 限制了相关DOM操作。

6 总结

  • 学习了客户端容器的相关知识,但是还是要多看多复习
  • 很开心自己的学习有所产出,以后复习时候也可以拿自己文章来复习

参考