上篇文章聊到:在 HTTP 2.0 时代以后,不需要额外担心由于 TCP 连接数带来的前端性能问题,因此我们不再需要雪碧图等优化手段了。于是前端工程师在 HTTP 协议这层能做的性能优化似乎只有「尽可能地减小资源体积」这一方向。

这篇文章会围绕这个主题,列举现阶段前端能在网络层面做的性能优化。

以图片为例:资源体积压缩

要说减少资源的体积,首当其冲的就是媒体资源了:图片、视频、音频等。

这里就拿图片举例。早在 Web 2.0 时代,那时短视频行业还没有兴起,一个最最最丰富的网站也不过是由文字和图片组成,比如大家经常访问的酒妖、草榴等知名网站。

比如我们打开酒妖的一个帖子(全是图片的那种),浏览器 tab 上的菊花在一直转圈,直到很久才加载完成,为什么呢?因为这个帖子的不仅有很多图片,还都是超清的那种,于是用来加载它们的时间就很长了。这里说的“加载”,实际上就是资源通过网络连接从服务端传输到浏览器端的过程。

有解决办法吗?当然有:减小资源体积呀。

就拿图片来举例子,tinypng / tinyjpg,全球知名的图片在线压缩工具。只要是对图片质量要求没那么苛刻的网站,用这种压缩图片工具把体积减小个 50%(甚至更多),普通人的肉眼几乎是看不出区别的。

图片压缩前后对比

比如上面这两只国宝,一个是压缩前(60 kb),另一个是压缩后(15 kb),各位能看出来哪个是哪个吗?

推翻无脑打包:按需加载

还记得上篇文章提到的“减少 HTTP 请求数量”的性能优化方法吗?其中最常用的就是把所有能打包在一起的静态资源都打包成一个文件,比如 JS、CSS 等。

但这样的做法没有问题吗?当然有,不然我也不会 cue 它。

打包资源这件事,主要有两个问题:

  1. 自从进入 HTTP/1.1、HTTP/2 以后,TCP 协议层已经做了很大程度的优化。对于前端来说,请求数量再也不是一个迫在眉睫的问题了

  2. 现代前端工程的复杂度今非昔比,复杂的交互逻辑、繁重的第三方依赖,如果再将所有资源文件打包在一起,那打包结果的体积将变得非常大,虽然请求数量得到了减少,但资源的下载速度反而变得很慢,得不偿失

比如下面这个例子,小明只想访问我的博客首页,但服务器把打包之后的 js 文件返回给了他(包含四个页面的 js),于是不仅浪费了网络带宽,还导致浏览器费劲解析了很多没用的 js,很没有必要。

只访问首页却得到了所有js

最理想的情况,就是下面这张图描绘的场景:当用户访问首页(index)时,只返回首页对应的资源。

访问首页只得到了首页的资源

拿 Vue 举例,只要在定义路由文件时用 dynamic import 的语法定义页面对应的组件,即可实现基于路由的组件按需加载。

// ...
{name: 'Home',path: '/home',component: () => import('@/components/Home.vue'),
}
// ...

Gzip:服务器端资源压缩

前后端一家亲,性能优化这件事情,如果后端的老哥能帮一把,那效果肯定是一加一大于二的。

HTTP 协议本身是支持多种报文压缩算法的,比如 gzip、deflate、br 等,它们有一个共同的名字:HTTP 压缩

我们就拿 gzip 举例子。浏览器向服务器请求资源时,请求头中有一个字段:Accept-Encoding,代表了浏览器支持的 HTTP 压缩算法。服务端在接受到这个信息后,会用浏览器支持的压缩算法对报文进行压缩,同时在响应头中附上两个关键字段:Content-EncodingContent-Length,前者表示当前使用的压缩算法,而后者是当前资源压缩后的大小。一般情况下,gzip 能将文本文件压缩为原来大小的 30%,奇效。

gzip.png

我们来看下服务器端控制 gzip 压缩的关键字段(nginx):

# ngx_http_gzip_module# 开启或关闭 gzip 功能
gzip: on | off# 设置 gzip 压缩文件使用缓存空间的大小
# 默认值:gzip_buffers 32 4k | 16 8k
gzip_buffers: number size# gzip 压缩力度,取值范围 1~9
# 数值越小,压缩力度越小,压缩得越快;数值越大,压缩力度越大,压缩得越慢
gzip_comp_level: level# 匹配浏览器的 UserAgent(支持正则表达式)
# 若命中匹配,则会关闭 gzip
gzip_disable regex# 开启 gzip 时最低的 HTTP 版本
zip_http_version: 1.0 | 1.1# 该指令用来指定资源的字节数
# 只有当资源的大小大于这个值时,才启用 gzip 压缩
gzip_min_length: length

如何解决服务端压缩的性能问题

目前看起来,服务端 HTTP 压缩是比较完美的优化方案,但,在技术领域是没有银弹的

银弹:Silver Bullet,在软件工程领域指一种能解决问题并且没有任何瑕疵的方法。

到底会有什么问题呢?

服务器在返回gzip压缩文件之前都做了什么

从图中可以看到服务端在向浏览器传递所需资源时的三个关键步骤。其中有个被虚线框起来的步骤,即“压缩”这一步:服务端在每一次返回资源前,都会都需要压缩资源进行压缩,而每一次压缩都是要消耗服务端的算力的。假设一个极端的情况,你的网站只有一个服务器,而用户却有十万人......慌了吗?

这个时候,就该伟大的前端工程师们出手了。如果我们能在前端就把资源都压缩好,再把压缩好的资源放在服务器上等待浏览器享用就行了。思路看起来没什么问题,能实现吗?难不成浏览器有这么大的能耐,还能压缩文件?

小了,格局小了。前端可不止浏览器哦,在前端工程化的世界里,“构建”可是一个很关键的步骤。这下各位思路就开阔了吧:没错,可以在构建的时候整些花里胡哨的,比如我们现在正需要的 gzip 压缩。

前端构建时gzip.png

这里举两个例子,一个是老牌王者 webpack,另一个是闪亮新秀 vite

如何在 webpack 中开启 gzip 压缩

webpack 对于 gzip 的配置还是蛮简单的,只需要一个叫做 compression-webpack-plugin 的插件就行:

const compressWebpackPlugin = require('compression-webpack-plugin');
// ...
configureWebpack: {plugins: [new compressWebpackPlugin({filename: '[path].gz[query]',algorithm: 'gzip',test: /\.(js|css)$/,threshold: 1024,minRatio: 0.8,deleteOriginalAssets: false,}),],
}
// ...

如何在 vite 中开启 gzip 压缩

如果说在 webpack 开启 gzip 的难度是 1 + 1,那在 vite 中开启 gzip 的难度就是 1 本身:

import viteCompression from 'vite-plugin-compression';
// ...
plugins: [ viteCompression() ],
// ...

诶,为什么能这么简单呢,因为 vite-plugin-compression 这个插件本身提供的配置是有默认值的,而这些默认值刚好满足我们基本的要求,所以就有了开箱即用的假象(大多数号称“开箱即用”的插件或工具,几乎都是因为默认值比较抗打罢了...)。

最后

至此,我们基于现代前端工程面临的网络协议(HTTP > 1.1),推翻了合并文件、雪碧图等这些既费力不讨好又过时的方案,又介绍了压缩图片、分包加载、资源压缩(gzip)等符合时代发展的性能优化方案。
不过,在性能优化这件事情上,没有所谓的“一招鲜吃遍天”,我们应当在实际工程中思考并产出符合业务要求回归技术本质的优化方案,要讲究因地制宜

✨原创精品文章,推荐阅读✨

(点击图片即可阅读)

关注后星标

回归 HTTP 协议本质:前端还能做哪些性能优化?相关推荐

  1. 前端面试被问到性能优化该肿么办!

    性能优化1 前端面试被问到性能优化该肿么办! 1.1 页面重构怎么操作? 网站重构:在不改变外部行为的前提下,简化结构.添加可读性,而在网站前端保持一致的行为. 也就是说是在不改变UI的情况下,对网站 ...

  2. 罗海雄:仅仅使用AWR做报告? 性能优化还未入门(含PPT)

    编辑手记:祝贺罗海雄老师加入Oracle ACE社区,他是数据库SQL开发和性能优化专家,也是ITPUB论坛的资深版主,我们整理了罗老师一篇AWR裸数据分析的文档,供大家学习参考(同款PPT和相关源码 ...

  3. 做 SQL 性能优化真是让人干瞪眼

    很多大数据计算都是用 SQL 实现的,跑得慢时就要去优化 SQL,但常常碰到让人干瞪眼的情况. 比如,存储过程中有三条大概形如这样的语句执行得很慢: select a,b,sum(x) from T ...

  4. 「前端那些事儿」② 极限性能优化

    前言 前端的工作并不仅仅是实现「视觉&交互稿」,想要开发一个高性能易维护的「完美」站点并未易事,针对前端的性能优化贯穿着项目开发的始终,绝不是交互口中的「拖拽工人」! 然而前端优化策略却是一件 ...

  5. 历年双11实战经历者:我们是如何做数据库性能优化及运维-CloudDBA和天象

    8月24日阿里云数据库技术峰会上,阿里云高级DBA专家玄惭带来面对超大规模的数据库集群,尤其是在每年像双11这样重大促销活动中,阿里云是如何进行运维和优化的.本文主要介绍了天象和CloudDBA两个产 ...

  6. 干了三年的Java,你竟然还不会MySQL性能优化

    摘要:MySQL性能优化就算通过合理安排资源,调整系统参数使MySQL运行更快,更节省资源.MySQL性能优化包括查询速度优化,更新速度优化,MySQL服务器优化等等. 前言 MySQL性能优化就算通 ...

  7. 如何使用UWA做游戏性能优化

    UWA是现在常用的Unity手游性能分析工具,好处是比Unity自带的工具或Xcode更详细和直观.最近公司的项目也在使用,将使用经验在此做个分享. 先看下UWA的产品线: GOT Local/Onl ...

  8. java mysql重要吗_干了三年的Java,你竟然还不会MySQL性能优化

    摘要:MySQL性能优化就算通过合理安排资源,调整系统参数使MySQL运行更快,更节省资源.MySQL性能优化包括查询速度优化,更新速度优化,MySQL服务器优化等等. 前言 MySQL性能优化就算通 ...

  9. Web前端教程分享:页面性能优化办法有哪些?

    引子 互联网有一项著名的8秒原则.用户在访问Web网页时,如果时间超过8秒就会感到不耐烦,如果加载需要太长时间,他们就会放弃访问.大部分用户希望网页能在2秒之内就完成加载.事实上,加载时间每多1秒,你 ...

最新文章

  1. Spring全局异常处理的三种方式
  2. NetBeans 时事通讯(刊号 # 55 - May 06, 2009)
  3. vue事件总线_[面试] 聊聊你对 Vue.js 框架的理解
  4. CF535C Tavas and Karafs 二分 + 结论
  5. leetcode64 最小路径和
  6. Spring boot MultipartResolver
  7. oracle仅部分记录建立索引的方法
  8. 准备成立公司开发 app 外卖应用,怎么起步?
  9. Access2016学习9
  10. 理解PHP网页运行原理
  11. 用vc++穷举windows应用程序密码(上)
  12. 史上首例!阿里程序员写的代码,被国家博物馆收藏了!
  13. 麒麟信安操作系统:挖掘场景,与云俱进 ——携手openEuler赋能关键行业应用
  14. 高考2021北京录取成绩查询,2021北京地区高考成绩排名查询,北京高考各高中成绩喜报榜单...
  15. android adc,Android配置ADC接口
  16. 区块链测试(一):测试人员初学区块链
  17. Stairway to SQL Server Security Level 3: Principals and Securables - SQLServerCentral
  18. 电子电路硬件学习目标
  19. Docker 详细教程
  20. 概率论发展史上的几个重要悖论

热门文章

  1. 5G DTU地下水水位监测
  2. 知名网站SWAG,因色情内容被警方封杀!
  3. Linux-RAID详解及配置
  4. 关于矩阵之行列式、方阵、逆矩阵的理解
  5. ztree 实现表格树
  6. 海外媒体发稿技巧和方法,海外媒体发稿怎么做?
  7. 华为交换机S5735使用dhcp绑定地址报错:Error: Invalid MAC address.
  8. docker 镜像一执行状态就变成 Exited 的原因
  9. SpringBoot不使用Quartz集成定时任务的两种方式
  10. onlyoffice 回调传参数_【onlyoffice中文指南】0-基本概念