lewenweijia / notes

🏊 dive dive diving
1 stars 0 forks source link

web优化 #43

Open lewenweijia opened 4 years ago

lewenweijia commented 4 years ago

https://github.com/berwin/Blog/issues w3c webperf会员大佬博客 嗨,送你一张Web性能优化地图

问题

如何进行系统性地页面优化

  1. 浏览器多进程架构 | 渲染主线程 | GUI线程和JS线程执行互斥 | 单处理管道的多任务调度策略 「前端进阶」从多线程到Event Loop全面梳理 从浏览器多进程到JS单线程,JS运行机制最全面的一次梳理

    `一个宏任务(JS线程) > 系列微任务(JS线程) > 渲染(GUI线程)`
    单次宏任务以及系列伴随微任务执行完毕, 渲染主线程检查GUI线程, 执行渲染, 出位图操作

俚语

页面优化

浅谈script标签中的async和defer

脚本并不关心页面的DOM元素(文档是否加载完毕), 并不会产生其他脚本需要的数据?:
async走起, 百度统计

脚本页面依赖页面的DOM元素, 或者被其他脚本依赖, defer走起:
1. 评论框 | 2. 代码语法高粱 | 3. polyfill.js

不确定是defer还是async? -> 那么defer稳妥些!

肯定是要隐身模式的啊, 去除所有浏览器插件的干扰的效果的呢
lewenweijia commented 4 years ago

优化场景 「前端进阶」高性能渲染十万条数据(时间分片) 对于大量数据渲染的时候,JS运算并不是性能的瓶颈,性能的瓶颈主要在于渲染阶段

raf? -> 系统来决定cb的执行时间
setTimeout的分批渲染, raf的分批渲染

最终?: raf + documentFragment(保存在内存中的啊, 是DOM节点, 但并不是DOM树的一部分) 减少页面
回流
lewenweijia commented 4 years ago
Event: mousemove/keydown | Timer Fired | Animation Frame Fired

开发网页? 用户体验 | 可访问性 | 安全性 => 跟呼吸一样自然和简单

以用户为中心的性能指标 User-centric Performance Metrics

拆分计算任务, 减少用户输入延迟(键盘/鼠标)

http2多路复用和server push的结合使用(一条流一个资源, 不需要显式请求资源, 服务器主动server push 推送)

一对多的流推送服务, 一个请求多个六推送
schedule to the next IdlePoint (协调调度到下一个空闲点)

http2: 多路复用, 请求优先级, 头部压缩, 服务端推送
h2? 啥都不变, 只是针对数据的传输格式做了重新定义
一方面完美地向下兼容, 对用户完全透明, 只会感觉到性能的提升

关键渲染路径(critical rendering path) 前置: 什么是关键渲染路径:阻塞页面的初始化渲染也就是FP/FCP的咯 控制三个变量的尽可能小化

个数: 减少个数 大小: 压缩大小 长度: 尽可能趁早加载关键资源, 减短路径长度

消除/使其变得不重要 => 压缩/优化, 最小化传输字节

lewenweijia commented 4 years ago

缓存

避免不必要的缓存开销 versioned url for long-lived caching: 长时间缓存的版本化url的啊

对第三方的tree shaking, 还不如直接cdn化的呢

工程化/性能优化/安全

largish: 稍大的 <-- somewhat large

document.body.childNodes[0].appendChild(component());

浏览器区分资源还是通过url的

window/global/self <==> browser/node.js/serviceWorker 简单地将sw想象成一个中间件就好了的, 中间人, 中间代理

尝试去拉取并安装sw

lewenweijia commented 4 years ago

事实: 网络能力和设备能力总是不对称的

  1. 好网络差设备
  2. 差网络好设备

对低端网络,传输大小至关重要 对CPU能力差的设备,解析、编译的时间十分重要 ==》 应该尽可能减低这两个指标的呢

两个指标:

  1. 网络传输时间
  2. JS的解析、编译、执行占用主线程过多的时间的啊
lewenweijia commented 4 years ago

保持其价值尽可能降低第三方脚本带来对我们网站的影响,

IntersectionObserver + + dataset IntersectionObserver + div + background-image

video标签视频加载的延迟?

  1. preload="none"
  2. poster="....png"

video => gif muted autoplay loop

首屏中的关键img资源直接用标准的img更快的啊

。。。抵制js实现懒加载带来的性能诱惑陷阱

首屏线 首屏线 + 向下适当缓冲区 => IntersectionObserver(cb, { rootMargin:" "})

图片、视频延迟加载? 减少不必要的下载:

  1. 流量
  2. CPU消耗

最大限度压缩所需下载量

压缩
。注释 + 空格移除
文本的数量进行计数压缩

基于文本资源的minified(html、css、js):

  1. gzip =》 针对文本资源压缩友好, 70%. 图片?其他算法处理过了的,gzip微乎其微

  2. minified =》2. gzip ====》 .min.js.zip

minified?: 需要用特定的工具针对特定的资源进行压缩:
1. js,移除注解、空格换行、变量名简化
2. css、移除注解、空格换行、重叠选择器合并
3. html、移除注解、空格换行
lewenweijia commented 4 years ago

服务器开启gzip,是回报率很高的一项劳作的啊

gzip后,体积反而变得更大?原本就高度压缩的了,内容比gzip所依赖存储压缩信息的成本还高 =》 设置进行gzip的文件最小阈值

tree shaking的好处?:

  1. 减少网络传输大小

  2. 减少js的解析、编译时间。js文件拉下来之后,肯定执行一次的啊(伪main)

  3. 避免不必要的下载

  4. 通过压缩技术优化每个资源的传输编码

  5. 利用缓存完全否定RTT

自有资源和第三方资源: 该资源是否遵循性能的最佳做法?压缩、缓存

第三方资源成为我们的单点故障? =》 也就是该资源不可用的时候,影响我们网页的性能和用户体验

基于文本的资源 [html、css、js]、png

css像素和设备像素的对应关系: 1个css像素刚好对应1个设备像素 1个css像素对应多个设备像素

设备像素越丰富,展示的效果越细腻

  1. 矢量图片
  2. 光栅图片

如果使用光栅图片,那么设置srcset、picture =》 提供图片的多个变体

svg?也是基于文本的资源的啊,也应该剔除注释、元信息、minified、gzipped

浏览器为光栅图片(不管什么格式)的每个像素始终占据4个字节的内存(rgba四通道信息) 500 × 500的像素的光栅图片 =》 1m左右

图片的格式选择:

  1. 通用格式:png(细节控)、jpeg(能显示就行)
  2. 现代客户端?:webp

三个能力:动画、透明度、浏览器支持度 webp支持动画、也支持透明度,和gif相差只有浏览器的支持程度了

多数cdn都会提供自动化图片优化服务

图片仍然是网络暴涨的原因

嘿嘿嘿, 图片优化是个精细活啊。。。 webp也是google家发明的啊

link下进行preconnect一个cdn站点,tcp消耗,tls消耗

webpack的js代码优化?
1. 减少重复代码 -》optimizaiton.splitChunks.cacheGroups => 不断的抽取公共代码
2. 动态导入

webpack的optimization里面配置
1. 压缩器:minimizer[ new TerserPlugin({}) ]
2. 公共模块抽取设置:splitChunks.cacheGroups

嘿嘿,都是通过白名单的形式的啊
lewenweijia commented 4 years ago

预提取和预加载 prefetch: 低优先级,浏览器空闲时,类RIC preload: 高优先级,不阻塞load时间情况下进行记载, 类raf

预提取总是地风险的, 不会浪费用户流量

预提取/预加载技术: dns-prefetch: renderer项目中大量使用 prefetch: 低优先级, 浏览器空闲 preload: 高优先级, 不堵塞load事件, 真正获取的时候网络进程直接走cache通道

lewenweijia commented 4 years ago

webpack的optimization.splitChunks下的智能代码分割

lewenweijia commented 4 years ago
最后来个资源提示的效果的
dns-prefetch
preconnect
prefetch
preload
性能优化?:
1. 资源加载优化
2. 渲染优化
lewenweijia commented 4 years ago

页面具有高可交互性,并且运行顺滑: 用户输入(键盘、鼠标、touch滚动) 动画

滚动应该像手指的滑动一样快

高性能网站和应用?

  1. 理解浏览器是如何处理HTML、CSS、JS,并确保代码(包括第三方代码)尽可能高效地进行运行
下面因素需要保持一致以获取最大的页面流畅度:
浏览器渲染动画和页面的速率 《===》 设备屏幕的刷新率 
lewenweijia commented 4 years ago

来来来,研究下为啥会出现卡顿感。。。(我只是分享我的发现和总结) 页面卡顿感?: 浏览器的渲染(出图)速率跟不上设备屏幕刷新率

卡顿、===》 用户体验

我们在意的是用户体验的效果的啊

如果处于交互状态,完全是js领导化的啊

布局、绘制、合成

渲染优化?这项工作是要浏览器配合的呢

sticky scrolling, 粘黏滚动 => 页面滚动跟手指滑动一样的快的效果的啊 闪烁更新,flickering update

布局和绘制是可选的啊,在渲染流水线(rendering pipeline)里面 layout property: 不改变元素的几何属性, 就不走layout步骤的啊 => 几何属性? width/height/position(top, left)信息, 宽/高/位置

最后的最后再走合成路线, 将他们合并回来

paint-only属性举例: background-image, text color, shadow, background-color

这个页面有几个图层的呢, 需要通过compositor进行合并页面的啊 页面由图层进行组成的

渲染流水线的第一个阶段: 可以引起视觉变化的统一(js、css改变、webanimation api)

渲染流水线,除了第一阶段和最后一阶段,其他的都是可选的啊

文本资源?
1. minified
2. comrpess
3. acahe

关键渲染路径?:浏览器获取资源到将它们渲染成页面的整个流程

lewenweijia commented 4 years ago

BIG DEAL

关键渲染路径
渲染流水线

资源优化


1. 移除不必要的代码
2. minify
3. compress
4. cache
``
1. 页面获取
2. 子资源获取

浏览器会干的事情,也是开发者预定好的那些事情的效果的啊

增量形式的HTML分发, incrementally HTML delivery

let's go to timeline and record

练习?探索时间线轨迹

grep location *, 命令行文件扩展符
lewenweijia commented 4 years ago

一帧结束的标识:像素被绘制到屏幕就好了的啊

js当然需要在一帧的开头进行尽可能早的执行:

  1. 因为js会触发style, layout, paint, composite一系列过程的啊

raf?make js code run at the right point of every frame`

raf?很棒的工具来进行动画的制作

浏览器是如何渲染一帧的:渲染流水线

在16ms的时间预算下, 任务可能会超时,浏览器自身也有一些内部任务
browser has housekeeping to do
lewenweijia commented 4 years ago

16ms? 浏览器每一帧也有内部工作要做,所以6ms给浏览器作为时间预算,那么我们就只有10ms了的啊

js代码在占据渲染流水线的时间,至多3/4的啊

样式计算
布局计算
绘制
合成(图层管理)
lewenweijia commented 4 years ago

js问啥要在渲染流水线的最前面?因为js会导致后面的任何一个渲染流水线子阶段重新执行的啊 可能导致很多工作redone 同时,也尽可能让js有更多的时间进行执行 。。。jQuery still use setTimeout for animation today

setTimeout的问题,v8引擎对对啥时候出图是没有感知的,傻傻的等timeout
raf,浏览器每次出帧的时候, 会自动去拿里面的东西

为什么React是RIC? 让更高优先级的用户输入和动画,可以流畅执行。而React的reconcilation任务属于CPU密集性,不属于高优先级任务,可以延缓

lewenweijia commented 4 years ago
function animate() {
  // Do something super rad here

  requestAnimationFrame(animate);
}

requestAnimationFrame(animate)
lewenweijia commented 4 years ago

raf, 最低版本IE9, setTimeout来作为polyfill的效果的啊。并不是一个理想的fallback,但是可以工作的啊

可怕的可怕的啊,JS的代码都跑在帧里面的正确时间的啊

need to fill all the work inside 16ms

need to fill all the work inside 16ms =》 js => style => layout => paint => composite 10-12ms的时间来跑js代码的情况的啊。。style => ... => composite这一段可以认为对开发者完全是 不透明的,是浏览器的housekeeping。浏览器提供两个逃生舱让我们可以参与渲染流水线的协调中来 分别是raf和ric的啊 raf:js代码可以

js代码很容易在一帧里面超出一开始的时间预算

framework/library? => they has their work to do ,而不是单单你写的那些代码了的啊。哈哈

timeline? 告诉js执行时间,哪个函数,在哪里

lewenweijia commented 4 years ago

and interact with the site

long-running JavaScript

通过Performance来查找长时间运行的JS代码的啊 这里我们会多出许多额外的信息,来帮助我们进行调研查找 find bottleneck more easily

sort fn? actually the built-in one is great!

Performance下的各种形式的火焰图的效果和形式的啊。flame view

主线程和worker线程互不干扰, 但是可以相互通信

main: consumeData(result) postMessage(params) worker: dowork(data) postMessage(result)

web worker对跑长时间js的任务来说, 无限价值的形式的啊。

spawn出一个新的ww线程

lewenweijia commented 4 years ago

284aec5bb7f16b3ef4e7482110c5ddbb_articlex


2151798436-59da4801c6772_articlex

lewenweijia commented 4 years ago

async,乱序。不依赖其他脚本 + 不操作DOM