共计 2380 个字符,预计需要花费 6 分钟才能阅读完成。
优化思路是什么?
BIG QUESTION: 当我们谈到一个 web 应用的性能优化,应该从哪些方面去考虑?
思路就是,当我们去访问一个 web 应用的时候,都做了哪些操作?对应这些操作的,就是我们所能进行的优化的模块!
浏览器请求 DNS 服务器,获取 IP 地址;
建立 TCP 连接;
浏览器发出详细请求,通常为 HTTP(s)、WebSocket 之类;
服务器响应请求,并返回数据;
浏览器渲染返回的数据到页面;
释放 TCP 连接;
那么,我们接下来就按照这个流程,一步一步来看如何进行优化。
不好控制和不重要的优化内容
1. DNS
首先,DNS 查询的流程如下图所示
当有浏览器缓存时,就不会去查询之后的步骤,有无缓存的对比如下图
可以看到,DNS Lookup 这一步,在有缓存之后就不会出现。
2. TCP 连接建立
同样如上图所示,Initial Connection 所占用的时间即为 TCP 建立连接的耗时。由于 TCP 建立需要 3 次握手的操作,使其成为 HTTP(s) 协议通信耗时最长的过程。
针对这个过程,我们可以使用 HTTP Keep-Alive 机制,来保持 TCP 连接状态,这样可以使客户端不需要在每次 http 请求的时候都去与服务器建立 TCP 连接,可以节省掉很大的时间开支、提高服务器吞吐率。
之所以说这个也是不好控制和不重要的优化点,是因为现代浏览器已经默认支持 Keep-Alive,而常用的 Web 服务器也都可以对应进行支持。
如需手动设置,要注意 timeout 和 max 参数,保持时间太长的 TCP 连接,也会对服务器造成无用资源消耗。
重要的优化内容
3. 浏览器请求和服务器响应
针对请求和响应的优化,简而言之,就是:
减少请求次数
降低请求耗时
在这里,可做的优化点包括:
CDN
压缩传输,即 GZIP/Deflate
前端模块化
使用缓存
使用本地存储
负载均衡:Nginx/SLB
3.1 CDN
CDN 是 Web 应用优化的基础,也是最重要最影响用户体验的一个环节!在项目中,需要注意将打包后的资源文件上传到 CDN 地址,并且在构建工具中配置相关 CDN 信息。
3.2 数据压缩
服务端与客户端的数据交互可通过压缩来进行优化,常用的压缩方式是 GZip 和 Deflate,本文以 GZip 为例。GZip 支持 HTML/CSS/JS/XML/PlainText 等多种格式的压缩。
下图可看出是否使用压缩,对于传输文件大小的影响。
3.3 前端模块化
前端模块化便于文件管理、也更利于资源归类压缩,模块化大致经历了如下历程。
script -> 闭包函数 -> AMD -> CMD -> CommonJS -> ES6
而对应的构建工具,也有以下发展历程。
Grunt/Gulp -> Browserify -> Webpack
前端模块化详情可参见《Web 前端模块化方法》
3.4 使用缓存
当客户端使用服务端返回的内容时,可以通过缓存机制,减少请求传输次数。缓存分为 强制缓存和协商缓存 两种。
强制缓存使用 Expires 和 Cache-Control:max-age 控制缓存有效时间。协商缓存使用 Last-Modified 配合 ETag 控制缓存有效时间。
通常来讲,系统优先匹配强制缓存。对于静态资源,系统需要做好相关缓存,避免重复请求。
3.5 使用本地存储
使用本地存储,可以在一定程度上减少服务器请求,也可以加快内容展示速度。
本地存储的使用有以下历程:
Cookie+ 变量 -> WebStorage -> 单页面内存式存储 -> IndexDB
变量 + Cookie
Cookie 被设计来管理状态,但在简单应用中可存储数据
4KB 限制 + 域名绑定
单页面内存式存储
针对单页面应用设计的变量存储
如 VueX
Web Storage
LocalStorage & SessionStorage
区别:生命周期、作用域
IndexDB
终极方案、NoSQL
3.6 负载均衡
通常负载均衡包含 4 中模式:
4. 浏览器渲染
4.1 Async 和 Defer
对于资源文件的引入,使用 async 和 defer。async 没有固定顺序,即加载到文件就会引入;defer 会按照 dom 顺序进行插入。
4.2 懒加载
内容的懒加载,如配合 vue-router 的按需加载;图片的懒加载,即需要展示时才去加载。
4.3 图片优化
图片优化是渲染层面能够最大程度提升性能的优化模块,也是操作起来最麻烦、需要投入精力最多的模块。
笔者认为大致分为三个方向:
源:确保所有的图片都从 CDN 源获取
裁剪:使用正确大小的图片
格式:按需使用格式
源和裁剪都比较明确,格式方面我们细说一下。
常用格式包括:
JPG:体积小、有损压缩、不支持透明
PNG:体积大、无损压缩、支持透明
SVG:文本文件、体积小、不失真、兼容性好
BASE64:文本文件、依赖编码、小图标解决方案;需要少量小图标时可以使用此方案,需要大量小图标时建议使用 CssSprites;
WebP 新格式,支持动图、体积小;浏览器支持的兼容性差。
# 阿里在 1688 网站上的使用方法可以借鉴:
https://alicdn.com/xxx.jpg_xxx.webp
4.4 Throttle & Debounce
节流(Throttle)在某段时间内,不论触发了多少次回调,都只做第一次,并在结束时给出响应。
防抖(Debounce)在某段时间内,不论触发了多少次回调,都只做最后一次,并在完成后给出响应。
节流和防抖的目标,都是减少执行,降低损耗,减少卡顿。
示例如下:
Throttle 示例
let flag = false
window.onscroll = () => {
if (flag) {
return
}
flag = true
setTimeout(()=>{
doSomething()
flag = false
})
}
Debounce 示例
<input onKeyUp=”kp()”>
var timer
var kp = ()=> {
clearTimeout(timer)
timer = setTimeout(()=> {
search()
}, 500)
}