前言
记录青训营前端专场的学习过程,有不足的地方还请大佬指正。
由于本人基础比较薄弱,所以笔记尽可能的详细。
该文章开始的版本将以简述课程知识点为主,等后面实践有自己的理解后会编辑添加自己的理解
浏览器架构
浏览器架构演进
- 单进程架构:所有模块都运行在一个进程里,包含网络,插件,javascript运行环境等
- 多进程架构:主进程、网络进程、渲染进程、GPU进程、插件进程
- 面向服务架构(多进场架构升级版):将原来的UI、数据库、文件、设备、网络等作为一个独立的基础服务
多进程分工
| 进程名称 | 进程描述 |
|---|---|
| 浏览器(主进程) | 主要负责页面展示逻辑、用户交互、子进程管理;包括地址栏、书签、前进、后退等 |
| GPU进程 | 负责UI绘制,包含整个浏览器的UI |
| 网络进程 | 网络服务进程,负责网络资源加载 |
| 标签页(渲染进程) | 控制tab内的所有内容,将Html、css和Javascript转化为用户可交互的内容 |
| 插件检查 | 控制网站运行的插件,比如flash、Modheader等 |
| 其他进程 | 比如 Storage/Network/Audio Service等 |
渲染进程
多线程架构的渲染进程组成
- js引擎线程:负责解析js脚本、运行js程序,每个渲染进程下面只有一个js引擎线程。与GUI渲染线程互斥,如果js任务执行过长,会导致页面卡顿。
- GUI渲染线程:负责渲染浏览器界面,解析html、css,构建dom树和render树、布局、绘制,与js引擎线程互斥,GUI更新会在js引擎空闲时立即执行。
- 事件线程:由宿主环境提供,用于控制事件循环,不断地从队列里取出任务执行。
- 网络线程:在XHR、Fetch等发起请求后新开一个网络线程请求,如果设置了回调函数,在状态变更时,将回调放入事件队列,等待js引擎执行。
- 定时器线程:定时器所在线程,setTimeout、setIntervel计时完毕后,将回掉添加到事件队列,等待js引擎执行。
js引擎vs渲染引擎
- 在v8引擎中,会将js里的高频函数转换成机器码
- js引擎和渲染引擎相互独立
- js引擎和渲染引擎之间通过Bridge交流
多线程工作流程
1、网络进程负责加载网页资源
2、JS引擎解析JS脚本并执行
3、JS解析引擎空闲时,渲染线程立即工作
4、用户交互、定时器操作等产生回调函数放入任务队列中
5、事件线程进行事件循环、将队列里的任务取出交给JS引擎执行
先执行同步代码,然后通过事件循环从任务队列里取出计时器任务,这个时候只有在10s的时候扔进的一个函数,所以也输出20,然后再10s后,也就是总共30s后,事件线程把定时器任务放进任务队列里,然后渲染进程通过事件循环取出任务并执行,最后输出30s左右(由于事件循环有时间误差)
Chorme 原理
如何展示网页
- 输入处理:1、用户输入url输入内容后,UI线程会判断输入的url地址还是query查询条件。2、如果是url直接请求站点资源。3、如果是query直接发给搜索引擎。
- 开始导航:当用户按下回车,UI线程会通知网络线程发起一个网络请求,来获取站点内容。请求过程中,tab处于loading状态。
- 读取响应:网络线程接受到http响应后,先检查响应头的媒体类型(MIME Type),如果响应主体是一个HTML文件,浏览器将内容交给渲染进程处理。如果拿到的是其他类型文件,比如(zip、exe等),则交给下载处理器处理。
- 寻找渲染进程:1、网络线程做完所有检查后,会告知主进程数据已准备完毕,主进程确认后寻找渲染进程。2、主进程通过IPC消息告知渲染进程去处理本次导航。3、渲染进程开始接收数据并告知主进程自己已开始处理,导航结束,进入文档加载阶段。
- 资源加载:1、收到主进程的消息后,开始加载HTML文档。2、除此之外还要加载一些子资源,比如一些图片,css样式文件以及javascript脚本。
- 构建渲染树:1、先构建DOM树,将HTML文本转换成浏览器能够理解的结构。2、构建CSSOM树,浏览器不认识css,需要把css转换成cssom。3、构建渲染树,渲染树是dom树和csssom树的集合。
- 页面布局:1、根据渲染树计算每个节点的位置和大小。2、在浏览器页面区域绘制元素边框。3、遍历渲染树,将元素以盒模型的形式写入文档流。
- 页面绘制:1、构建图层:为特定节点生成专用图层。2、绘制图层:一个图层分成很多绘制指令,然后将这些指令按顺序组成一个绘制列表,交给合成线程。3、合成线程接收指令生成图块。4、栅格线程将图块进行栅格化。5、显示在屏幕上。
跨端容器(跨端方案)
Webview
- webview即网页视图,用于加载url展示内容的控件
- 可以嵌在移动端app内,实现前端混合开发,大多数混合框架都是基于Webview的二次开发;比如lonic,Cordova
Webview使用原生的能力
Javascript调用native
- API注入:Native获取Javascript环境上下文,对其挂载的对象或者方法进行拦截
- 使用Webview url scheme 跳转拦截
- IOS上window.webkit.messageHandler通信
Native调用Javascript
- 直接通过webview暴露的API执行JS代码
- IOS webview.stringByEvaluatingJavascriptFromString
- Android webview.evaluateJavascript