- web浏览器以及跨端方案
1浏览器架构
1.1浏览器架构演进
-
单进程架构:所有模块运行在同一个进程里,包含网络、插件、js运行环境
-
多进程架构:主进程、网络进程、渲染进程、GPU进程、插件进程->各个进程相对独立
- 虽然各进程分配独立内存区域,但是有些进程功能可能较大,耦合度高
-
面向服务架构:将原来的UI、数据库、文件、设备、网络等,作为一个独立的基础服务,模块划分更细
- 服务模块划分更细,更加内聚,耦合度更低
1.2多进程分工
| 进程名称 | 进程描述 |
|---|---|
| 浏览器(主进程) | 主要负责页面展示逻辑,用户交互,子进程管理;包括地址栏、书签、前进、后退、收藏夹等 |
| GPU进程 | 负责UI绘制,包含整个浏览器的全部UI,不是tab页里面的东西 |
| 网络进程 | 网络服务进程,负责网络资源加载 |
| 标签页(渲染进程) | 控制tab内的所有内容,将html、css和js转换为用户课交互的网页 |
| 插件进程 | 控制网站运行的插件,比如flash、modheader |
| 其他进程 | 适用程序:storage/network/audio service |
2.渲染进程
2.1常见浏览器内核
2.2多线程架构
- 渲染进程内部是多线程实现,主要负责页面渲染,脚本执行,事件处理,网络请求
| 线程 | 功能 |
|---|---|
| js引擎 | 负责解析js脚本,运行js程序,每个渲染进程下面只有一个js引擎线程。与gui渲染线程互斥,如果js任务执行事件过长,会导致页面卡顿 |
| gui渲染 | 负责渲染浏览器界面,解析html、css,构建dom树和render树、布局、绘制。和js引擎线程互斥,gui更新会在js引擎空闲时立即执行 |
| 定时器触发 | 定时器所在线程,setTimeout、setInterval计时完毕后,将回调添加到事件队列,等待js引擎执行 |
| 网络线程 | 在XHR、Fetch等发起请求后新开一个网络线程请求,如果设置了回调函数,在状态变更时,将回调放入事件队列,等待js引擎执行 |
| 事件触发 | 由宿主环境提供,用于控制事件循环,不断地从事件队列了取出任务执行 |
-
js引擎 vs gui引擎
- 解析执行js
- xml解析生成渲染树,显示在屏幕
- 桥接方式通信
2.3多线程工作流程
- 网络线程负责加载网页资源
- js引擎解析js脚本并且执行
- js解析引擎空闲时,渲染线程立即工作
- 用户交互、定时器操作等产生回调函数放入任务队列中
- 事件线程进行事件循环,将队列里的任务取出交给js引擎执行
- 以下代码在浏览器环境下输出顺序、内容
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)//输出?
3.Chrome运行原理
3.1如何展示网页
- 浏览器地址输入url后发生了什么
3.2输入处理
-
用户url框输入内容后,ui线程会判断输入的是url地址还是一个query查询条件
- 如果是url,直接请求站点资源
- 如果是query,将输入发送给搜索引擎
-
例如输入
www.baidu.com和输入百度回车后不同的效果
3.3开始导航
-
当用户按下回车后,UI线程通知网络线程发起一个网络请求,来获取站点内容
-
请求过程中tab处于loading状态
3.4读取响应
- 网络线程接收到http响应后,先检查响应头的媒体类型(MIME Type)
- 如果响应主体是一个html文件,浏览器将内容交给渲染进程处理
- 如果拿到的是其他类型文件,比如zip、exe等,则交给下载管理器处理
3.5寻找渲染进程(render)
-
网络线程做完所有检查后,会告知主进程数据已经准备完毕了,主进程确认后为这个站点寻找一个渲染进程
-
主进程通过IPC消息告知渲染进程去处理本次导航
-
渲染进程开始接收数据并告知主进程自己已经开始处理,导航结束,进入文档加载阶段
渲染进程工作流程
3.6资源加载
-
收到主进程的消息后,开始加载html文档
-
除此之外,还需要加载子资源,比如图片、css样式文件以及js脚本
3.7构建渲染树
- 构建DOM树,将HTML文本转化成浏览器能够理解的结构
- 构建CSSOM树,浏览器同样不认识CSS,需要将CSS代码转化为可理解的CSSOM
- 构建渲染树,渲染树是DOM树和CSSOM树的结合
3.8页面布局
-
根据渲染树计算每个节点的位置和大小
-
在浏览器页面区域绘制元素边框
-
遍历渲染树,将元素以盒模型的形式写入文档流
3.9页面绘制
-
构建图层:为特定的结点生成专用图层
-
绘制图层:一个图层分成很多绘制指令,然后将这些指令按顺序组成一个绘制列表,交给合成线程
-
合成线程接收指令生成图块
- 将指令整合
-
栅格线程将图块进行栅格化
- 转成位图,使用GPU加速
-
展示在屏幕上
4.前端优化
4.1首屏优化
-
压缩、分包、删除无用代码
-
静态资源分离
-
js脚本非阻塞加载
-
缓存策略
-
Ssr
-
预置loading、骨架屏
4.2渲染优化
-
GPU加速
-
减少回流、重绘
-
离屏渲染
- 先提前进行渲染
-
懒加载
-
提前加载到本地,需要时从缓存中去
-
4.3JS优化
-
防止内存泄露
-
注意全局变量
-
dom引用
-
定时器
- 可以自动清除定时器
-
-
循环尽早break
-
合理使用闭包
-
减少dom访问
-
防抖、节流
-
Web workers
5.跨端容器
5.1为什么需要跨端
-
开发成本低、效率高
- 多端可以使用
-
一致性体验
-
前端开发生态
5.2常见跨端方案
-
Webview
-
小程序
-
RN/WeeX
-
Lynx:字节内部的方案
-
Flutter
5.3WebView
-
网页视图,用于加载网页url,并展示其内容的控件
-
可以内嵌在移动端app内,实现前端混合开发
-
常见的webview分类
-
优势
- 一次开发,处处使用,学习成本低
- 随时发布,即时更新,不用下载安装包
- 移动设备性能不断提升,性能有保障
- 通过jsbridge和原生系统交互,实现复杂功能
-
webview使用原生能力
-
webview<->native(jsBridge)
5.4小程序
-
架构
- 渲染层-webview
- 双线程,多webview架构
- 数据通信,native转发
5.5react native/weex
- 原生组件的渲染
- react/vue框架
- Virtual dom:是dom的一个对象
- jsbridge
5.6Lynx
- 基于vue框架
5.7flutter
5.8通用原理
- UI组件
- 渲染引擎
- 逻辑控制引擎
- 通信桥梁
- 底层API抹平表现差异