Web应用性能优化随笔

优化思路是什么?

BIG QUESTION: 当我们谈到一个web应用的性能优化,应该从哪些方面去考虑?

思路就是,当我们去访问一个web应用的时候,都做了哪些操作?对应这些操作的,就是我们所能进行的优化的模块!

  1. 浏览器请求DNS服务器,获取IP地址;
  2. 建立TCP连接;
  3. 浏览器发出详细请求,通常为HTTP(s)、WebSocket之类;
  4. 服务器响应请求,并返回数据;
  5. 浏览器渲染返回的数据到页面;
  6. 释放TCP连接;

那么,我们接下来就按照这个流程,一步一步来看如何进行优化。


不好控制和不重要的优化内容

1. DNS

首先,DNS查询的流程如下图所示

Web应用性能优化随笔

当有浏览器缓存时,就不会去查询之后的步骤,有无缓存的对比如下图

Web应用性能优化随笔

可以看到,DNS Lookup这一步,在有缓存之后就不会出现。

2. TCP连接建立

同样如上图所示,Initial Connection 所占用的时间即为TCP建立连接的耗时。由于TCP建立需要3次握手的操作,使其成为HTTP(s)协议通信耗时最长的过程。

针对这个过程,我们可以使用HTTP Keep-Alive机制,来保持TCP连接状态,这样可以使客户端不需要在每次http请求的时候都去与服务器建立TCP连接,可以节省掉很大的时间开支、提高服务器吞吐率。

之所以说这个也是不好控制和不重要的优化点,是因为现代浏览器已经默认支持 Keep-Alive,而常用的Web服务器也都可以对应进行支持。

如需手动设置,要注意 timeoutmax 参数,保持时间太长的TCP连接,也会对服务器造成无用资源消耗。

重要的优化内容

3. 浏览器请求和服务器响应

针对请求和响应的优化,简而言之,就是:

  1. 减少请求次数
  2. 降低请求耗时

在这里,可做的优化点包括:

  1. CDN
  2. 压缩传输,即GZIP/Deflate
  3. 前端模块化
  4. 使用缓存
  5. 使用本地存储
  6. 负载均衡:Nginx/SLB

3.1 CDN

CDN是Web应用优化的基础,也是最重要最影响用户体验的一个环节!
在项目中,需要注意将打包后的资源文件上传到CDN地址,并且在构建工具中配置相关CDN信息。

3.2 数据压缩

服务端与客户端的数据交互可通过压缩来进行优化,常用的压缩方式是 GZipDeflate,本文以 GZip为例。
GZip支持 HTML/CSS/JS/XML/PlainText等多种格式的压缩。

下图可看出是否使用压缩,对于传输文件大小的影响。

Web应用性能优化随笔

3.3 前端模块化

前端模块化便于文件管理、也更利于资源归类压缩,模块化大致经历了如下历程。

script -> 闭包函数 -> AMD -> CMD -> CommonJS -> ES6

而对应的构建工具,也有以下发展历程。

Grunt/Gulp -> Browserify -> Webpack

前端模块化详情可参见 《Web前端模块化方法》

3.4 使用缓存

当客户端使用服务端返回的内容时,可以通过缓存机制,减少请求传输次数。
缓存分为 强制缓存协商缓存 两种。

强制缓存使用 ExpiresCache-Control:max-age 控制缓存有效时间。
协商缓存使用 Last-Modified 配合 ETag 控制缓存有效时间。

通常来讲,系统优先匹配强制缓存。
对于静态资源,系统需要做好相关缓存,避免重复请求。

3.5 使用本地存储

使用本地存储,可以在一定程度上减少服务器请求,也可以加快内容展示速度。

本地存储的使用有以下历程:

Cookie+变量 -> WebStorage -> 单页面内存式存储 -> IndexDB

变量 + Cookie

  • Cookie 被设计来管理状态,但在简单应用中可存储数据

  • 4KB限制 + 域名绑定

单页面内存式存储

  • 针对单页面应用设计的变量存储
  • 如VueX

Web Storage

  • LocalStorage & SessionStorage
  • 区别:生命周期、作用域

IndexDB

  • 终极方案、NoSQL

3.6 负载均衡

通常负载均衡包含4中模式:

Web应用性能优化随笔

4. 浏览器渲染

4.1 Async和Defer

对于资源文件的引入,使用 asyncdefer
async 没有固定顺序,即加载到文件就会引入;
defer会按照dom顺序进行插入。

4.2 懒加载

内容的懒加载,如配合 vue-router的按需加载;
图片的懒加载,即需要展示时才去加载。

4.3 图片优化

图片优化是渲染层面能够最大程度提升性能的优化模块,也是操作起来最麻烦、需要投入精力最多的模块。

笔者认为大致分为三个方向:

  1. 源:确保所有的图片都从CDN源获取
  2. 裁剪:使用正确大小的图片
  3. 格式:按需使用格式

源和裁剪都比较明确,格式方面我们细说一下。

常用格式包括:

  1. JPG:
    体积小、有损压缩、不支持透明
  2. PNG:
    体积大、无损压缩、支持透明
  3. SVG:
    文本文件、体积小、不失真、兼容性好
  4. BASE64:
    文本文件、依赖编码、小图标解决方案;
    需要少量小图标时可以使用此方案,需要大量小图标时建议使用CssSprites;
  5. 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)
}

相关推荐