浏览器执行原理
js运行环境是什么样子的呢?(简介了解)
-
浏览器基本组成结构
- 界面控件:包括地址栏,前进后退,书签菜单等窗口上除了网页显示区域以外部分
- 浏览器引擎:查询和操作渲染引擎的接口
- 渲染引擎:负责显示请求的内容,比如请求到HTML,它会负责解析HTML,CSS并将结果显示到窗口中
- 网络:用于网络请求,如组合框和窗口。它提供平台无关的接口,内部使用操作系统响应实现
- js解释器/js引擎:用于解析执行javascript代码
- 数据存储持久层:浏览器把需要的数据存在硬盘上,如cookie和web database(location、session)
-
浏览器进程
- 渲染进程(Render Process) (主线程)
- 将HTML,CSS和js转换为用户可以与之交互的网页,排版引擎Blink和js引擎V8都运行该进程中
- 每个Tab标签创建一个渲染进程
- 浏览器进程
- 主要负责界面显示,用户交互,子进程管理同时提供存储功能
- GPU进程
- GPU的使用初始是为了3D css的效果。随后网页的UI界面都选择GPU来绘制,这使得GPU成为浏览器普遍的追求
- Network Process 网络进程
- Plugin Process 插件进程
-
主线程
一个Tab窗口就是一个独立的渲染进程,而一个渲染进程则是有多个线程组成的:主线程,Worker线程,Compositor(排版)线程,Raster(光棚)线程。我们前端所熟悉的HTML,DOM树,CSSOM树,JS解析执行,渲染进程,页面的计算都在这一个线程中。主线程阻塞,页面就展现的慢。主线程奔溃,这个Tab窗口就奔溃了 。我们常见的标准规范也都在渲染进程的主线程里。渲染进程的主线程,是一帧一帧的绘制的。大多数情况下,我们的刷新率都是60fps,也就是说每帧执行间隔为17ms
主线程是单线程:
如果js被设计了多线程,如果有一个线程要修改一个dom元素,另一个线程要删除这个dom元素,此时浏览器就会一脸茫然,不知所措
备注 js线程和render进程互斥
-
浏览器的绘制机制
- 渲染引擎首先解析HTML文档,生成DOM树
- CSS样式会解析生成CSSOM树,根据DOM树与CSSOM树生成一颗用于渲染的树(Render Tree)
- 然后对渲染树的每个节点进行布局处理,确定其在屏幕上的显示位置(布局Render树)
- 遍历渲染树并用UI后端层将每一个节点绘制出来
二.联系的知识点
-
重绘(repaint)和回流(reflow)
- 回流:重新计算节点的尺寸和位置 (资源消费比较大)
- 重绘:节点的颜色、轮廓等样式属性发生了改变,不影响布局
- 回流必然引起重绘
优化:
- js尽量减少访问dom节点和css属性,多个dom操作可以合并到一个操作
- 减少不必要DOM层次,会导致大量时间在reflow上
- 不要从父级来改变子元素样式,最好直接改变子元素样式
-
改变阻塞模式:defer与async
- 当script上有defer和async属性时,script的下载均不会阻塞html的解析,但一旦含有async属性的脚本被下载完,他就会立即执行(执行时会阻塞html的解析),
- 含有defer属性的脚本则是在html解析完后(DOMContentLoaded触发前)才执行,没有defer和async属性的脚本在下载时会阻塞html的解析,下载完还会继续阻塞html的解析
d触发前)才执行,没有defer和async属性的脚本在下载时会阻塞html的解析,下载完还会继续阻塞html的解析