我只想这样
就这样
不跳了,我决定继续更新,慢慢写
就是整理一下,不想太乱。
我尽量以一个偏全栈能力的角度去完整地整理 Web 性能优化相关的知识,而不是局限于 Web 客户端的形式化优化。
也许不是每个类别都很详细,事实上几乎每个细节都能够拿出来长篇大论。
我把 Web 的优化点分为下面四个类别:
程序
资源
网络
渲染
好,从头开始。
因为我们做优化的本质是让客户端程序(Web App)以条件内最优的状态到达客户端,并最优地执行,所以客户端程序本身才是真正的核心。
而一个丰富的 Web 客户端会包含各种视频、音频、图片、文字、字体...等多种资源,资源的协调者便是 JavaScript 脚本(或 HTML),所以其实从优化来说,各占一半的重要性,OK,先说程序。
程序(算法、设计模式的优化,还有类似事件代理这样的特定平台优化...)
算法
数据结构、算法,与语言无关,是程序真正的 “原力”,所以 Web 开发者(特别是只专注于 Web site 那种)不要刻意去忽略,甚至应该加以重视。
我们假设几个例子:
我们假设有一个 User-List
用以存储...
[ 待更 ]
设计模式
一般除却游戏开发和框架等基建开发,很少用到设计模式,就先不说了。
每一种设计模式都是现实生活中的思想在程序中的映射,理解便好。
[ 待更 ]
程序设计
如果你只是想创建一个例如下拉菜单这样的功能,那么尽量用 CSS 代替 JavaScript,CSS 在客户端本身上进行高度优化,并有浏览器的本地预编译的支持。 如果使用这些预定义函数,不仅可以节省编译 JavaScript 的时间,还可以减少代码体积。至少客户端 API 针对 CSS 平台进行了优化,并且可能会使用 GPU 和其他一些无法用 JavaScript 控制的底层优化。
eval
、with
、try catch
...等语句在非必要时候尽量避免使用,js 脚本运行时依赖宿主环境的预读优化生成中间码并执行,这些语句块内的代码都无法被优化,速度可能相差几十倍,不过调试确实很有用。
try {
eval(code)
} catch (e) {
if (e instanceof SyntaxError) {
alert(e.message)
} else {
throw(e)
}
}
变量的就近维护
...
[ 待更 ]
DOM 相关
<ul id="ul">
<li>111</li>
<li>222</li>
<li>333</li>
<li>444</li>
</ul>
// bad code
const Li = Ul.getElementsByTagName('li')
Li.forEach(li => {
li.onclick = event => {
alert(li.innerText)
}
})
// 事件代理
const Ul = document.getElementById("ul")
Ul.onclick = event => {
event = event || window.event
var target = event.target || event.srcElement
if (target.nodeName.toLowerCase() === 'li') {
alert(target.innerHTML)
}
}
[ 待更 ]
简单说,资源优化的目的是:保证首屏 HTTP 请求数量和资源体积之间取得最佳平衡。
当然,绝大多数时候,资源都是通过首屏加载完毕的,所以首屏这个节点至关重要。
图片
图片是最常见的富文本资源形式,常用格式有:jpg
png(8/24)
gif
webp
svg
...
如果效果真的需要图片来表现,那么选择图片格式是优化的第一步。我们经常听到的词语包括矢量图、标量图、SVG、有损压缩、无损压缩等,首先要知道各种图片格式的特点:
图片格式 | 压缩方式 | 透明度 | 动画 | 浏览器兼容 | 适应场景 |
---|---|---|---|---|---|
JPEG | 有损压缩 | 不支持 | 不支持 | 所有 | 复杂颜色及形状、尤其是照片 |
GIF | 无损压缩 | 支持 | 支持 | 所有 | 简单颜色,动画 |
PNG | 无损压缩 | 支持 | 不支持 | 所有 | 需要高品质全透明 |
APNG | 无损压缩 | 支持 | 支持 | Firefox Safari iOS Safari | 需要半透明效果的动画 |
WebP | 有损压缩 | 支持 | 支持 | Chrome、Opera、Android Chrome、Android Browser | 复杂颜色及形状、浏览器平台可预知 |
SVG | 无损压缩 | 支持 | 支持 | IE8+ | 简单图形,需要良好的放缩体验/需要动态控制图片特效 |
其中 APNG
和 WebP
格式出现的较晚,尚未被 Web
标准所采纳,只有在特定平台或浏览器环境可以预知的情况下加以采用,虽然均可以在不支持的环境中较好的功能降级,但这里暂不讨论这两种格式。图片格式选择过程如下:
资源(图片格式的使用及 Base64,CSS 的分包或不分包处理、脚本的模块化处理、字体媒体等其他资源的压缩和生成)...
[ 待更 ]
Web server(包含 gzip
这类东西)、CDN、HTTP 强弱缓存、HTTP2、跨域预请求的优化)...
HTTP 缓存
首先,服务端给客户端资源响应时,在头部会告诉客户端这个资源的一些元信息,如:最后修改时间、唯一 hash 值、最大缓存时间...,客户端根据这些信息来决定自己要不要发起真正的请求。
强缓存:服务端告诉客户端,某一个资源在某一个时间点之前我一定不会更新,你不需要向我发起请求,所以我们在 Network 可以看到这类请求的 status 为 "from disk cache/from memory cache", 即不需要真正地发起网络请求,而是直接读取本地缓存。
from memory cache:在进程中内存读取数据,一般为窗口未关闭,刷新时,浏览器会直接读取此类数据;一般浏览器用来存放体积较小的资源,如 Base64 的图片,或其他资源等。
from disk cache:在本机磁盘缓存文件中读取数据,一般与进程无关,除非你清空浏览器缓存了;可以看到很多的 js、css 都来自 disk cache。
有一种说法是:三级缓存原理
弱缓存:客户端依然向对应地址发起请求,同时会附带上次拉取资源时服务端给的头部信息,如:唯一 hash 值, 服务端根据客户端给的信息来判断客户端缓存的文件和他要访问的存放在服务端的文件是否一模一样未被修改,若未被修改,则返回空数据,HTTP code 为 304, 客户端收到状态码便知道服务端的资源没有变动,可以直接使用本地缓存。
注意,两种缓存是建立在本地已有此资源的缓存的情况下。
在不同版本的 HTTP 协议中,由于新版协议需要兼容旧的协议,所以浏览器及 Web server 在处理 header 头时也会有优先级判断,且在某些极端情况下,不同的元信息字段可能会带来不同的结果。
last-modified
(HTTP/1.0),资源的最后更新时间,精确到秒,若一个资源在 1 秒内被修改多次,那么这个字段提供的信息将会导致异常结果,所以只适用于对资源变动不敏感的场景。
ETag
(HTTP/1.1)假设一个资源 a 被修改为 b,又被修改为 a,那么 ETag
可能是无法体现出来的,事实上任何一个 Web server 可能都有自己的计算规则,所以难以作证。
一般我们会同时使用,Web server 若支持 HTTP/1.1 协议,则会优先验证 ETag
。
[ 待更 ]
负载均衡、智能 DNS、Web server 分发,数据库连接池分发、多级缓存)...
[ 待更 ]
[ 待更 ]
因为在 HTTP/1.1 及之前版本中,浏览器对同一个域(域名、端口、协议)的最高并发数是有限制的,不同浏览器大概是 2-8 个左右的限制。
旧的方案有:静态资源多域名、CDN 域名,来分担 HTTP/1.1 浏览器对连接并发的限制, 缺点是,首次加载会有 DNS 压力,(具体关于 DNS 的整个过程怎么解析的,可以阅读 网络链路和跨域 )优点是利用不同域名突破资源加载瓶颈, 使静态资源路径与业务分离,可以减少很多没必要的 header 头数据的传输。
从 HTTP/2 开始,协议加入了 多路复用、二进制分帧、首部压缩、服务端推送 等几个核心的特性。
多路复用:允许同时通过单一的 HTTP/2 连接发起多重的请求 - 响应消息。
二进制分帧:将 header、body 封装为更小粒度的二进制数据,用于在 “应用层” 和 “传输层” 之间交换数据,且数据的交互都在一个 HTTP/2 连接上完成,无需 HTTP/1.1 的频繁握手等底层连接动作。
首部压缩:将重复的 header、字段信息合并,使用 HPACK 算法将信息进行压缩,相比 HTTP/1.1 减少了大量无用堆叠、重复、庞大数据的传输。
服务端推送:服务端能够更快的把资源主动推送给客户端。例如服务端可以主动把 js 和 CSS 文件推送给客户端,而不需要客户端解析 HTML 再发送这些请求。当客户端需要的时候,它已经在客户端了。
[ 待更 ]
这个部分和 网络链路和跨域 解析有重合
[ 待更 ]
部分资源参考源:
https://segmentfault.com/q/1010000002433991
因为回流是倒回去重新渲染,所以回流比重绘更花费时间,也就更加影响性能。所以在书写HTML代码时候尽量避免过多的回流。
回流的原因
[ 待更 ]
还可以
看到createDocumentFragment表示很开心,毕竟自己引发出来的讨论,哈哈哈😜😜
一起守过长城的,就叫战友!
2333333333333
沙发,占坑,坐等更新
reply:
来自长者的慈爱关怀已进了炮膛,好好感受下温暖
reply:
2333333