js放到页面最后就不会阻止gui的情况了
浏览器 js异步会阻止dcl渲染么
defer 属性:用于开启新的线程下载脚本文件,并使脚本在 HTML 文档解析完成后执行,一定会在 DOMContentLoaded 事件触发之前执行
async 属性:HTML5 新增属性,用于异步下载脚本文件,下载完毕立即执行代码,脚本也会在 load 事件触发之前执行完
css选择器的解析是从右向左解析的。试想一下从左向右进行匹配的话,样式系统会从左到右一直匹配,直到匹配到,如果读到最后一个不匹配,那么就放弃,就很费时耗能。所以从右向左解析,一开始就筛选掉大部分不和匹配的节点。
打印:
在浏览器地址栏输入URL,按下回车后究竟发生了什么?
DOMContentLoaded与load的区别、触发时机
浏览器连接限制
defer async 针对script标签
preload,prefetch 针对 link,style,font
浏览器的渲染
1. 传输过程
2. 主线程 html的解析,位置计算,layoutTree
3. 合并线程 瓦片过程,栅栏为位图过程,Activation阶段,draw阶段
4. GPU渲染过程
重要指标:18k这种
DCL,L
fp,fmp,fcp
lcp 1m
cls 0.1
fid 100ms
tti
浏览器的进程和线程
浏览器渲染原理及流程
浏览器渲染原理
前端浏览器渲染原理及优化
图解浏览器渲染原理及流程
渲染中的GPU流水线
GPU渲染流水线
进程和线程
进程是应用程序执行的最小单位;
线程是进程的程序执行的最小单位;
进程互相独立,有各自的独立内存空间;
进程动态生成,动态灭亡;
进程有1个或者多个线程组成,所有线程共享进程的内存;
浏览器的进程和线程
浏览器有4个进程:浏览器渲染进程,浏览器主进程、插件进程、GPU3d绘制进程
渲染进程主要有5个线程,GUI渲染线程,js引擎线程,事件触发线程,定时触发器线程,异步http请求线程;
GUI渲染线程是负责解析css和dom,构建DOM树和renderObject树;重绘或者回流会执行该线程;GUI渲染线程和JS引擎线程是互斥的,执行JS引擎线程的时候;GUI线程会被挂起;
JS引擎线程也称为JS内核,负责处理Javascript脚本程序。(例如V8引擎)
JS引擎线程负责解析Javascript脚本,运行代码。
JS引擎一直等待着任务队列中任务的到来,然后加以处理,浏览器无论什么时候都只有一个JS线程在运行JS程序
同样注意,GUI渲染线程与JS引擎线程是互斥的,所以如果JS执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞。
事件触发线程,用户交互事件,推入该线程等待js线程执行完后推入执行;
定时器触发线程,setTimeout setInterver,等到回调后,推入js线程执行队列
异步线程,等待完成把回调后推入js线程执行队列;
性能博客
浏览器渲染原理及性能优化
Web性能领域常见的专业术语
FP、FCP、FMP、LCP都是什么P?
前端页面性能指标
重要文件的大小预算小于170kb
切割文件的标准是18k。
交互延迟100ms的响应时间
fps 60fps的祯
首屏小于1250ms.
fmp 首次有效加载
fcp 首次最大加载
lcp 最大加载
tti 可交互时间
FCI 第一次CPU空闲,主线程空闲就代表可以接收用户的响应了
LCP 最大内容渲染时间
DCL DomContentloaded事件触发的时间
L 表示onLoad事件触发的时间。
首屏结束时间小于1250ms = FCP(首屏内容绘制)或者LCP(最大内容绘制),FMP(有效内容绘制)
FPS 50-60
LCP 最大内容渲染时间, 用来衡量页面加载性能, 小于2.5s
CLS 测量视觉稳定性 小于0.1
FID 用于度量用户第一次与页面交互的延迟时间,衡量交互性能 小于100ms
在浏览器地址栏输入URL,按下回车后究竟发生了什么?
1). 浏览器通过DNS将域名解析为ip。
2).通过DNS解析得到了目标服务器的IP地址后,与服务器建立TCP连接。
- ip协议: 选择传输路线,负责找到
- tcp协议: 三次握手,分片,可靠传输,重新发送的机制
- http
3).找到对外服务器,对内服务器,找到html文件返回。
这个时候,浏览器的几个线程和进程开始工作。
4进程,5个线程
5).浏览器GUI渲染线程,收到html后,浏览器的渲染进程中gui线程开始解析html,是一个深度递归遍历过程。词法分析语法分析,生成ast树的过程。
6)其中可能遇到css,js,直接发起请求获取,去请求cdn的过程。cdn缓存服务器。
7) 请求资源是并行的,统一域名最多6个,但是他们的执行时机需要注意,css执行和html的解析是并行的,而js的执行会等待已经加载的 css执行完成,所以这里就有优化点。js加载会等待css都解析完成,js的加载会阻塞html继续往后执行。
8).解析html为html树,解析css为css-tree, 而js通过JS引擎线程解析执行,不停的重绘重排,合称为render tree。
9). 主渲染线程做ast的解析,布局计算,而合并线程计算光栅栏这些信息,然后交给GPU线程,然后交给浏览器渲染。
JS CSS 如何阻塞页面渲染
页面优化-为什么script最好放底部link最好放头部
我们不讨论内联,就讨论远程加载的情况
html分为,html解析和html渲染。
css的加载和渲染不会影响html的解析,但是会影响html的渲染,css的加载会影响js的加载和执行。
js的加载和执行会阻塞html的解析和渲染。但是js的加载只会阻塞了js后边的html的解析,但是不会阻止已解析html的渲染。
问题1:css放前边的原因。 1 怕css影响js的加载,影响整体的渲染。2 害怕css会影响html的渲染。
问题2:script放后边的原因。1 不影响后端html的解析。 2 也不影响前边html的渲染。
问题3:为啥script放后边只会影响后边的渲染,而不阻塞前边的渲染?因为渲染的过程中分为了主线程渲染和合并线程渲染,GPU渲染,js加载影响了主线程渲染的渲染,但是后边的已经解析的html到合并线程渲染和GPU的渲染并不会影响。
DOMContentLoaded与load的区别、触发时机 https://www.jianshu.com/p/c3384c315d40
DOMContentLoaded,初始的 HTML 文档被完全加载和解析完成之后,而无需等待样式表、图像和子框架的完成加载。
load,所有的图片,样式,子框架都加载完成。
js的defer或者async webpack的import动态语法导入。
脚本:async,defer属性,让浏览器异步加载,解决脚本阻塞渲染问题
preload与prefetch博客1
preload与prefetch博客2
---defer async 针对script标签
- defer 和 async 在网络读取的过程中都是异步解析,不会影响html解析。
- 但是defer的执行,会等html的解析完成,但是在dcl之前(统计中),而async加载在html解析之后,但是加载完直接执行,与DCL无关,一般在DCL之后。
- 多个defer是有顺序依赖的,多个async并没有顺序。
- defer在DCL之前,async 和DCL无关,一般在DCL之后。
----preload,prefetch 针对 link,style,font等。
preload 可以强制浏览器在不阻塞onload 事件的情况下请求资源,是一个声明式 fetch。(当前页面一定会用到,首页对应的资源),如果相同的资源发起请求(不带preload,如果带preload会走两次)会走缓存。还可以定义资源加载完毕后的回调函数,media,crossorigin跨域。
prefetch 告诉浏览器在空闲时才开始加载资源;(可能会用到的资源,非首屏幕的资源,未来页面的懒加载)
preload as="style" 将会获得比 as=“script” 更高的优先级。不带 as 属性的 preload 的优先级将会等同于异步请求。
在link标签中加入rel=“preload” as = “font”该元素属性,不会造成渲染阻塞。
async fetch Prefetch preload
Async defer 加载的时候都是并行的,async是加载完立刻执行,而defer等dom树解析完成后执行, defer在dcl之前的。
preload 和 prefetch 都是预先下载,不会执行,当需要的时候就后缓存了。
preload一般是本页面需要的,而prefetch是其他路由页面需要的。
更细粒度用 important(high,auto,low)
性能分析
Performance
浏览器Performance面板性能监控详解
chrome浏览器性能分析
测试
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=s, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div>123123231</div>
<div id="t1"></div>
<script>
function aaa() {
for (var i = 0; i < 100000; i++) {
console.log(1);
}
document.getElementById('t1').innerHTML = 't1';
}
var flag = 0;
setInterval(() => {
if (flag < 3) {
flag++;
aaa();
}
}, 2000);
</script>
</body>
</html>
选择cpu密集区域(大概t1和t1稍微前边一些)
浏览器连接限制
浏览器会限制同一域名的HTTP并发连接数,这定义在HTTP规范(RFC2616)中。大多数现代浏览器针对每个域名允许发起六个并发连接,而多数旧版浏览器每个域名只允许两个并发连接。
HTTP 1.1 协议规定单用户客户端不应该与任何服务器或代理保持两个以上连接,这就是浏览器限制连接数的原因。
为啥需要浏览器链接并发限制
因为浏览器对同一域名下的最大连接数做了限制,为了让浏览器并发加载,将资源分散到不同域名下,缺点是需要DNS解析更多的域 名。
http1.1版本有限制,http2好像就没有了限制了
多标签之间怎么通信?
localStorage:在一个标签页监听localStorage的变化,然后当另一个标签页修改的时候,可以通过监听获取新数据
WebSocket:因为websocket可以实现实时服务器推送,所以服务器就可以来当这个中介者。标签页通过向服务器发送数据,然后服务器再向其他标签推送转发
ShareWorker:会在页面的生命周期内创建一个唯一的线程,并开启多个页面也只会使用同一个线程,标签页共享一个线程
postMessage:
// 发送方
window.parent().pastMessage('发送的数据','http://接收的址')
// 接收方
window.addEventListener('message',(e)=>{ let data = e.data })
复制代码
进程间通信的方式
管道通信:就是操作系统在内核中开辟一段缓冲区,进程1可以将需要交互的数据拷贝到这个缓冲区里,进程2就可以读取了
消息队列通信:消息队列就是用户可以添加和读取消息的列表,消息队列里提供了一种从一个进程向另一个进程发送数据块的方法,不过和管道通信一样每个数据块有最大长度限制
共享内存通信:就是映射一段能被其他进程访问的内存,由一个进程创建,但多个进程都可以访问,共享进程最快的是IPC方式
信号量通信:比如信号量初始值是1,进程1来访问一块内存的时候,就把信号量设为0,然后进程2也来访问的时候看到信号量为0,就知道有其他进程在访问了,就不访问了
socket:其他的都是同一台主机之间的进程通信,而在不同主机的进程通信就要用到socket的通信方式了,比如发起http请求,服务器返回数据
1 传输过程
输入url发送请求,获取html的内容,然后html解析式,字节流变为字符流,然后词法分析,然后找到css和js也发出请求,
所以要求
使我们客户端和服务器的keep-alive要长一些,避免短时间内的tcp多次 握手
减少http请求树
我们的dns解析要快, dns缓存, dns优化
图片多域名并发, 多个域名保存静态文件地址,防止浏览器的对相同域名的限制
io的文件内容要尽量的小
—压缩体积, 可能涉及到压缩的算法gzip
—去掉没必要的内容(可以考虑css的减少的插件和js减少的插件)
—顺序加载,空闲加载,懒加载,先加载重要的内容,后加载不重要的内容
2.渲染进程-gui线程-渲染的过程
Bytes→characters→tokens→nodes→objectmodel 模型
html->通过html的解析器,解析为Dom树
js->通过js的解析器,解析执行
css->css解析器
css执行会阻塞js的执行
js加载然后会等待css执行完,然后执行,js会阻塞html的解析。
html最后生成的dom树会和css生成的css树进行一起渲染生成render树。
render树经过布局计算,layoutTree
经过层级计算 变为图层树
paint,把一系列绘制操作记录在一个显示列表上。Paint Records(多个渲染层,有的地方称为合成层)。
3.-合并线程渲染的,浏览器统一表示为Composite Paint Records渲染的过程(transform可以直接把变为合成层)。
commit tiling raster active draw
commit 阶段主线程把多个渲染层交接给合成线程的拷贝放入合成线程。随后主线程便会进入下一帧的渲染流程中。两个线程同步进行,互不影响。commit
Tiling阶段。把纸上的内容拿出来一层层的刷瓦。
Raster阶段,光栅化就是将图像画进位图的过程。光栅化结束后这些位图会上传至GPU内存之中。
Activation阶段 一帧画面只有真正activation之后变成active Tree才算进入渲染流程。
draw阶段 每个tile都会被“绘制”成“绘图块,而所有绘图块会被包装在一个CompositorFrame对象中。这个对象就是最终合成线程的终点,或者说,它就是整个renderer。
4 GPU渲染过程,process的最终输出。整合CompositorFrame,让GPU输出,如果有浏览器插件也会在这个阶段进行。
GPU 的渲染过程。
GPU 顶底着色器,片源着色器 图片。
css 的渲染层合成是什么 浏览器如何创建新的渲染层
在 DOM 树中每个节点都会对应一个渲染对象(RenderObject),当它们的渲染对象处于相同的坐标空间(z 轴空间)时,就会形成一个 RenderLayers,也就是渲染层。
渲染层将保证页面元素以正确的顺序堆叠,这时候就会出现层合成(composite),从而正确处理透明元素和重叠元素的显示。对于有位置重叠的元素的页面,这个过程尤其重要,因为一旦图层的合并顺序出错,将会导致元素显示异常。
https://www.jianshu.com/p/125c5e9159b5
https://www.jianshu.com/p/e6252dc9be32
https://juejin.im/entry/5a9a379af265da239d48c027
这里分为了5个步骤
主线程程 dom style layout (图层渲染 composition update) paint
此时会讲绘制过程记录在一个纸上边
合成线程 commit tiling raster active draw
commit阶段,主线程会提交一份cc layer的拷贝放入合成线程。随后主线程便会进入下一帧的渲染流程中。两个线程同步进行,互不影响。commit阶段虽然会短暂阻塞主线程,但是时间开销很小。
Tiling阶段。把纸上的内容拿出来一层层的刷。普瓦。
Raster阶段,光栅化就是将图像画进位图的过程。光栅化结束后这些位图会上传至GPU内存之中。
Activation阶段 一帧画面只有真正activation之后变成active Tree才算进入渲染流程。
draw阶段 每个tile都会被“绘制”成“绘图块(draw quads),而所有绘图块会被包装在一个CompositorFrame对象中。这个对象就是最终合成线程的终点,或者说,它就是整个renderer process的最终输出。这个对象会被提交给browser process的display阶段 整合CompositorFrame,让GPU输出,如果有浏览器插件也会在这个阶段进行。
Html 渲染 Js 渲染和css渲染之间阻塞
https://www.cnblogs.com/gg-qq/p/11327972.html
这两个图我们可以看出来,css的加载解析不会影响html的解析是并行的,但是css的加载解析会阻塞dom树的渲染。另外css的加载解析不会阻塞js的加载,但是会影线js的执行。
cdn,压缩,缓存,减少http请求数据,内敛样式。
主要是介绍浏览器的渲染过程,但是没有分析js脚本文件解析过程。
(一)浏览器渲染进程包含1、解析HTML文件和CSS文件,加载图片等资源文件,渲染成用户看到的页面;2、执行解析js文件脚本代码。
(二)整个过程浏览器会开启多个线程协作完成,包括:GUI渲染线程,JS引擎线程,事件触发线程,定时器触发线程,异步HTTP请求线程。
(三)其中GUI渲染线程和JS引擎线程是相互排斥的,因为JS引擎线程在执行的时候有可能会发生重绘和回流。
https://www.cnblogs.com/chengxs/p/10403622.html
你真的了解回流和重绘吗
https://juejin.im/user/5a9f77666fb9a028c14a01eb
GPU渲染流水线
https://www.cnblogs.com/xhg986/p/7454187.html
了解GUI渲染线程的执行过程,我们可以根据原理进行渲染优化:
1、尽可能早的提前引入css文件,例如在头部引入css文件。
2、尽可能早的加载css文件中的引入的资源,例如自定义字体文件,可以使用预加载,在link标签中加入rel=“preload” as = “font”该元素属性,不会造成渲染阻塞。
3、在DOM和CSS渲染之后加载js文件,例如在尾部加载js文件,或者使用该元素属性defer和async,进行js问价异步加载,但是不同的浏览器会有兼容性问题。
送你一张图,搞懂性能优化,再也不怕面试官拷问. https://juejin.im/post/5e7723636fb9a07cc321675d
前端黑科技:美团网页首帧优化实践 https://juejin.im/post/5bee7dd4e51d451f5b54cbb4
浏览器的HTMl解析器 https://www.jianshu.com/p/8b4d9db3fd02
硬件加速 https://segmentfault.com/a/1190000013869580
从浏览器渲染原理,说一说如何实现高效的动画 https://segmentfault.com/a/1190000019713766
GUP渲染 https://blog.csdn.net/leoysq/article/details/51457727?depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-4&utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-4
Web性能领域常见的专业术语
https://github.com/berwin/Blog/issues/46
2018你应该知道的Web性能信息采集指南
https://github.com/berwin/Blog/issues/25