虽然他是从事网络优化工作的专家,但是网络这个领域是大家共有的,所以个人认为,无论是哪个职业的朋友都可以从中受益。在前两期文章中,我们探讨了在代码层面进行性能优化的方法,本期我们将带来网络传输层的优化内容,这也是性能提升三部曲的终结篇:全面提升网络表现:Web前端优化专家级助手系列之网络篇。
首先,让我们回顾一下HTTP请求的完整过程:DNS解析、建立TCP连接、发送请求报文、处理响应报文和关闭TCP连接。在这其中,DNS解析是非常关键的一环,以下是具体的解析步骤:
- 浏览器先在自身的DNS缓存中搜索;
- 如果自身缓存中没有找到,则会继续在系统自身的DNS缓存中查找;
- 若仍未发现相关记录,则尝试从hosts文件中获取信息;
- 如果以上三个过程均未获得结果,浏览器将递归地请求域名服务器进行查询。
成功解析到域名对应的IP地址后,浏览器会以一个随机的端口(14~65535)向服务器的WEB程序(如httpd、nginx)等的80端口发送建立一个TCP连接的成功链接请求。这个过程经历了原始的HTTP请求通过TCP/IP 4层模型的层层封装。
当连接请求到达服务器端时,它会经历以下步骤:
- 经历各种路由设备(局域网内除外);
- 进入网卡;
- 进入内核的TCP/IP协议栈;
- 有可能经过Netfilter防火墙(属于内核模块)的过滤;
- 最终达到WEB程序并建立TCP连接。
在TCP连接的三次握手/四次挥手中,HTTPS协议还有ssl握手的环节。以下是HTTP请求和响应的基本结构:
-
Web浏览器发送HTTP请求报文,该报文由以下三部分组成:
- 请求行
- 请求头
- 请求正文
-
Web服务器发送HTTP响应报文,它也由以下三个部分组成:
- 状态码
- 响应头
- 实体内容
当Web服务器关闭TCP连接时,一个简单的宽带环境(无本地缓存)的请求耗时大致为47ms。这个时间包括了DNS解析、TCP握手、SSL协商、一次延迟、网络传输层等多种因素。
为了优化这个过程,我们提供以下方案:
- 优化DNS解析速度:使用DNS缓存可以加速DNS解析过程;
- 使用DNS负载均衡:为相同的域名配置多个IP地址,在响应DNS查询时,DNS服务器将会按主机记录的IP地址顺序返回不同的数据,从而实现负载均衡的目的。
接下来,我们将详细介绍如何提高缓存性能:
- 强缓存和协商缓存:
- 当浏览器加载资源时,首先根据该资源的HTTP头部判断它是否命中强缓存;
- 如果强缓存命中,浏览器直接从自己的缓存中读取资源,无需向服务器发送请求;
- 当强缓存未命中时,浏览器会发送一个请求到服务器,通过比较资源的HTTP头部来判断协商缓存是否命中;
- 如果协商缓存命中,则服务器将不会返回资源的数据,而是告诉客户端可以直接从缓存中加载该资源;
- 共同点:如果命中缓存,都将直接从客户端缓存中加载资源,而不是从服务器加载数据;
- 区别:强缓存不需要向服务器发送请求,而协商缓存需要。
缓存实现方式包括:
- 本地磁盘和内存的缓存模式:本地模式主要应用于无痕浏览,在窗口关闭时清除磁盘缓存。
- 实现缓存的具体方法包括 Expires、ETag、Last-Modified、keepalive 和 Cache-Control 等 headers。
现在,让我们来看看如何利用 ServiceWorker 进行优化:
- 谷歌开发的 ServiceWorker 在后台启动了一条服务 worker 线程,其作用是无论打开多少个页面,都只有一个 ServiceWorker 在管理,从而提高性能;
- 结合 Web App Manifest,可以实现在线离线访问,断网时返回内容,提示用户将网站加入桌面等。
最后,如何利用浏览器开发工具进行优化?以下是一些实用的功能:
- console.log:不解释;
- console.table:以表格形式打印复杂的数据结构;
- console.dir:递归打印对象的所有属性;
- console.trace():追踪函数的调用轨迹;
- console.group()、console.groupEnd():分组打印信息;
- 可带样式打印;
- 检查无用的CSS/JS等。
综上所述,通过合理优化网络传输层性能,我们可以显著提升整个Web页面的加载速度和用户体验。希望这篇文章对您有所帮助!