浏览器
- 浏览器是多进程的,js是单线程的。进程:程序运行,资源分配。线程:进程中独立执行的流
- 浏览器有哪些进程
Browser进程: 浏览器的主进程(负责协调、主控)
GPU进程: 最多一个,用于3D绘制等
浏览器渲染进程:默认每个Tab页面一个进程,互不影响
第三方插件进程:每种类型的插件对应一个进程,仅当使用该插件时才创建
注:在浏览器中打开一个网页相当于新起了一个进程(进程内有自己的多线程)
- 浏览器内核(渲染进程)是多线程的
**GUI渲染线程与JS引擎线程互斥:**由于JavaScript是可操纵DOM的,如果在修改这些元素属性同时渲染界面(即JS线程和UI线程同时运行),那么渲染线程前后获得的元素数据就可能不一致了。
url到render
第一阶段:Browser进程
浏览器输入url -> 浏览器主进程接管,开一个下载线程 -> http请求(DNS解析、TCP协议的三次握手和四次挥手、HTTPS和HTTP的区别(HTTP2)等等操作)-> 等待响应,获取内容 -> 通过RendererHost接口转交给Renderer进程
第二阶段:Renderer进程 浏览器内核
渲染进程处理 Web 页面的所有内容
文档—>DOMTree —> CSSDOM —> Layout —> LayerTree —> paint -> composite —> raster(位图) —> GPU绘制
DomTree构建 DOM 树: html 转换为 DOM 树
Style样式计算:
将css文本转换为 styleSheet。document.styleSheets
标准化属性值(em, rem, 字体的加粗(blod),颜色等)。
计算 DOM 树中的每个节点的样式 ComputedStyle
复制代码
Layout布局: 计算 DOM 树中的 可见元素 的几何位置,生成布局树。
LayerTree分层:为特定的节点生成专用的图层,生成图层树(图层叠加后合成最终页面)
并不是布局树中的每个节点都会生成图层。
如果这个节点没有对应的层,那么它属于父节点的图层。
拥有层叠上下文属性的元素会生成新的层
复制代码
Composite合成层:特定css属性节点:(position:fixed||stiky & 位置不为空…)
Paint图层绘制: 把图层绘制拆分为绘制指令,按照顺序组成待绘制列表,主线程把待绘制列表交给合成线程,合成线程把图层分为图块(tiles)。
Raster栅格化: 把图块转换成位图,生成的位图保存在 GPU 内存中。
Display合成和显示:提交给浏览器进程DrawQuad消息进行绘制,最终显示在屏幕上。
onReadyStateChange、DOMContentLoaded
Chrome Performance 工具
googlechrome.github.io/devtools-sa… demo
performance
performance面板有如下四个窗格:
1、controls。开始记录,停止记录和配置记录期间捕获的信息
2、overview。页面性能的高级汇总(W、A、S 和 D 键调整您的选择。 W 和 S 分别代表放大和缩小。 A 和 D 分别代表左移和右移)
3、火焰图。 CPU 堆叠追踪的可视化
4、统计汇总。以图表的形式汇总数据
Redering
小功能:查看合成层、显示实时FPS面板
Layer
合成层细节和原因
window.performance
前端性能监控和报警
memory字段代表JavaScript对内存的占用。chrome拓展对象
navigation字段统计的是一些网页导航相关的数据:
- redirectCount:重定向的数量(只读),但是这个接口有同源策略限制,即仅能检测同源的重定向;
- type 返回值应该是0,1,2 中的一个。分别对应三个枚举值:
- 0 : TYPE_NAVIGATE (用户通过常规导航方式访问页面,比如点一个链接,或者一般的get方式)
- 1 : TYPE_RELOAD (用户通过刷新,包括JS调用刷新接口等方式访问页面)
- 2 : TYPE_BACK_FORWARD (用户通过后退按钮访问本页面)
最重要的是timing字段的统计数据,它包含了网络、解析等一系列的时间数据。
-
startTime:有些浏览器实现为navigationStart,代表浏览器开始unload前一个页面文档的开始时间节点。比如我们当前正在浏览baidu.com,在地址栏输入google.com并回车,浏览器的执行动作依次为:unload当前文档(即baidu.com)->请求下一文档(即google.com)。
-
如果当前文档为空,则navigationStart的值等于fetchStart。
-
redirectStart和redirectEnd:如果页面是由redirect而来,则redirectStart和redirectEnd分别代表redirect开始和结束的时间节点;
-
unloadEventStart和unloadEventEnd:如果前一个文档和请求的文档是同一个域的,则unloadEventStart和unloadEventEnd分别代表浏览器unload前一个文档的开始和结束时间节点。否则两者都等于0;
-
fetchStart是指在浏览器发起任何请求之前的时间值。在fetchStart和domainLookupStart之间,浏览器会检查当前文档的缓存;
-
domainLookupStart和domainLookupEnd分别代表DNS查询的开始和结束时间节点。如果浏览器没有进行DNS查询(比如使用了cache),则两者的值都等于fetchStart;
-
connectStart和connectEnd分别代表TCP建立连接和连接成功的时间节点。如果浏览器没有进行TCP连接(比如使用持久化连接webscoket),则两者都等于domainLookupEnd;
-
secureConnectionStart:可选。如果页面使用HTTPS,它的值是安全连接握手之前的时刻。如果该属性不可用,则返回undefined。如果该属性可用,但没有使用HTTPS,则返回0;
-
requestStart代表浏览器发起请求的时间节点,请求的方式可以是请求服务器、缓存、本地资源等;
-
responseStart和responseEnd分别代表浏览器收到从服务器端(或缓存、本地资源)响应回的第一个字节和最后一个字节数据的时刻;
-
domLoading代表浏览器开始解析html文档的时间节点。我们知道IE浏览器下的document有readyState属性,domLoading的值就等于readyState改变为loading的时间节点;
-
domInteractive代表浏览器解析html文档的状态为interactive时的时间节点。domInteractive并非DOMReady,它早于DOMReady触发,代表html文档解析完毕(即dom tree创建完成)但是内嵌资源(比如外链css、js等)还未加载的时间点;
-
domContentLoadedEventStart:代表DOMContentLoaded事件触发的时间节点:
-
页面文档完全加载并解析完毕之后,会触发DOMContentLoaded事件,HTML文档不会等待样式文件,图片文件,子框架页面的加载. document.ready
-
domContentLoadedEventEnd:代表DOMContentLoaded事件完成的时间节点,此刻用户可以对页面进行操作,也就是jQuery中的domready时间;
-
domComplete:html文档解析完成、网页内资源准备就绪;
-
loadEventStart和loadEventEnd分别代表onload事件触发和结束的时间节点
1. DNS 查询耗时
domainLookupEnd – domainLookupStart,如果使用了 DNS 缓存或采用了持久连接,值为 0
2. TCP链接耗时
connectEnd – connectStart,如果采用了持久连接,值为 0
3. request请求耗时
responseStart – fetchStart,这个指标可以反映出网络和后端处理的整体耗时
4、解析dom树耗时
= domComplete – domInteractive
5. 白屏时间
白屏时间指页面展示出第一个元素的时间,主要通过看到是 DOM 解析完成的时间,domInteractive – fetchStart
6. 首屏时间(onload时间)
首屏时间指第一屏页面完全展示完毕的时间,loadEventStart – fetchStart
知道这些有什么用呢?难道就是为了装一下X吗?
performanc优化
从渲染流程总结性能优化,先看一下优化标准
RAIL(Response、Animation、Idle、load)性能评估模型
以用户为中心;最终目标不是让您的网站在任何特定设备上都能运行很快,而是使用户满意。
- 立即响应用户;在 100 毫秒以内确认用户输入。
- 设置动画或滚动时,在 10 毫秒以内生成帧。 1000/10=100fps
- 最大程度增加主线程的空闲时间。 50 毫秒
- 持续吸引用户;在 1000 毫秒以内呈现交互内容。 渐进式渲染、主要内容渲染
渲染流程总结性能优化
一、DNS 解析
每次dns解析大概需要20-120毫秒
- 允许使用浏览器DNS缓存机制 (IE缓存30分钟、Firefox ]&Chrome缓存 1 分钟 )
- 减少DNS查询 (组件分散在 2~4 个域名下)
- dns-prefetch www.taobao.com/
DNS prefetching 允许浏览器在用户浏览页面时在后台运行 DNS 的解析
二:http请求
- preconnect 允许浏览器在一个 HTTP 请求正式发给服务器前预先执行一些操作(DNS 解析,TLS 协商,TCP 握手)
- 减少tcp连接时间:http Keep-Alive
- http头文件最小化 (Cookie压缩、使用不带 Cookie 的域名)
- 减少http请求次数和大小 (避免 src、href空值、js、css、icon、third party plugins、Use less code)
- 避免301/302重定向(重定向将产生额外的往返时间)
- 最大化下载线程:使用不同的域名可以最大化下载线程,但注意保持在 2
4 个域名内,以避免 DNS 查询损耗(iE 813 chrome&firebox 6) - HTTP/2:1、头文件压缩 2、多路复用的单一长连接 3、服务端推动Sever Push
- 打包配置优化
三:render
- preload 允许浏览器预加载在 CSS 和JavaScript 中定义的重要资源
- **图片优化:**图片压缩、图片cdn、预加载、懒加载 getBoundingClientRect()
- 避免Dom阻塞
避免css阻塞render-tree渲染 (选择器、less css、minify)
避免加载js阻塞render-tree生成 (async or defer)
避免js引擎线程阻塞GUI渲染线程
- 延迟加载:页面初始加载时哪些内容是绝对必需的?(渐进增强、懒加载)
- 预加载:利用浏览器空闲的时间
- 减少dom数量 (document.getElementsByTagName(‘*’).length)
- 减少重绘和回流
- 一定会引起layout的属性:“
offsetTop、offsetLeft、offsetWidth、offsetHeight
scrollTop、scrollLeft、scrollWidth、scrollHeight
clientTop、clientLeft、clientWidth、clientHeight
getComputedStyle()
getBoundingClientRect()
-
需要大量操作的dom直接删除,新增
-
requestAnimationFrame
-
避免频繁操作样式,最好一次性重写style属性
-
Composite 开启硬件加速
- 最常用的方式:translate3d、translateZ
- will-chang属性(这个比较偏僻),一般配合opacity与transform使用(其它属性并不会变成复合层), 作用是提前告诉浏览器要变化,这样浏览器会开始做一些优化工作(用后释放)
- opacity属性/过渡动画(需要动画执行的过程中才会创建合成层,动画没有开始或结束后元素还会回到之前的状态)
- <canvas><canvas><webgl>等元素
三:缓存
CDN缓存
- 针对静态资源,所有正常状态码(大于等于 200 小于 400)均缓存 8 天。特别地,301 响应缓存 2 小时,302 响应缓存 20 分钟;
- 针对动态资源,程序会自动识别,则不进行缓存;
- 对于其他大于等于 400 的不正常响应,则不进行缓存;
- 缓存节点通知浏览器缓存的具体时间由 HTTP 响应头里面的 Cache-Control 和 Expires 响应头控制。
浏览器缓存
- Expires 有效期
- Cache-Control max-age
- Last-Modified 日期
- ETag 文件版本标记
有趣的现象
- 如果从A⻚面打开B⻚面,且A和B都属于同一站点(相同的协议和根域名)的话,那么B⻚面复用A⻚面的渲染进程;如果是其他情况,浏览器进程则会为B创建一个新的渲染进程。eg:zhidao.baidu.com
- Cookie设置在第一域名时,在其子域名中无法删除
参考文章
推荐文章
Resource Hints – What is Preload, Prefetch, and Preconnect?
developers.google.com/web/tools/c…
webkit技术内幕