前段时间给我的博客做了一下加载速度优化,同事笑称我的“优化”都是好几百年前的技术了😂。不过我很多年没有认真做前端了,这个博客 justinyan.me 搬过几次Server,但一直用的是Wordpress,接入是Nginx。除了最近两年把图片搬到腾讯云CDN之外就没做过什么优化,也难怪要被同事嘲笑。
以下是我对这个陈年老博客做过的优化,有些是之前做过的,记录一下供以后参考。这些想必早成前端基础,专业人士莫笑。😁
P.S. 这篇文章是6月份开始写的,7月18日我们发布了《中文播客榜》xyzrank.com也用上了了所有的优化,现在想来,技术的东西总是一开始折腾,后来就成为下一个项目的基础了。
一、把静态资源搬到CDN
一般是图片、音频、视频等较大体积的资源,不会跟着 HTML 一起接收的,就托管到 CDN 上。JS/CSS 等一般不怎么变化的文件也可以托管到 CDN 上。
早年间JS/CSS文件由服务器直接host,我们一般在URL后面加上 ?version=xxx
参数来解决浏览器缓存问题。现在要搬上CDN就不能这么干了,因为CDN缓存的是文件,跟URL的query无关。这时候就需要用上Webpack的content hash来解决这个问题。
我现在建站一般使用Webpack或Vite (for Vue 3项目)作为流程构建工具,如果大家使用Webpack的话,可以参考官方文档: Caching | webpack
原理是为正式环境编译文件时,根据文件内容计算content hash并作为URL路径的一部分,这样每次修改代码hash就会变,浏览器和CDN的Cache也就跟着变了。
CDN 服务的话,如果面向的用户群体在国内的话,建议选择国内的云服务,腾讯云,阿里云,七牛,又拍云等非常多可选。虽然国外的 Cloudflare 有免费的 CDN 额度,但是因为众所周知的原因,如果想要国内用户有较好的浏览体验的话还是用国内的吧。
另外想用国内的 CDN 服务需要走“各种繁琐的手续”,但(¯_(ツ)_/¯),还是走一遍吧。
搞定 CDN 服务之后,Wordpress上我安装了 CDN Enabler 插件,它做的事情就是在下发 HTML 之前,把我文章里所有的 https://justinyan.me 开头的 URL,替换成我的 CDN 域名。非常简单。
其他静态站点可以直接手动传到CDN,想做自动化的话一般各家都有自己的SDK可用。我的 Just Focus for Mac就是自己写了脚本,一键编译,打包,自动上传CDN,更新Server地址的。(感谢前同事 @dangrover多年前给我介绍的 The Joel Test: 12 Steps to Better Code – Joel on Software,自那以后我所有的项目都必须支持一键编译部署。)
二、使用Lighthouse找出优化点
刚开始工作的时候我针对公司项目一个大文件读取进行了优化,因为读取量是以前的三分之一,所以我当时跟我的 Leader 说我的优化效果理论上可减少三分之二的耗时,性能提升三倍。我的 Leader 跟我说,优化必须要有数据,不能靠猜,所以需要跑一下 Profile 来证明我的结论。
自那以后我就记得,一切优化必须有数据做支撑,否则你也许做了负优化都未可知。
前端的优化工具很多,Chrome 自带的 Dev Tools 里就有个超好用的 Lighthouse 工具,可以帮我们分析出当前页面存在的问题。Lighthouse分为几个大项:
- Performance
- Accessibility
- Best pratices
- SEO
- Progressive Web App
为了减少缓存优化带来的误判,建议在“隐身模式”(Incognito)下运行。跑完一次分析之后,工具会给出各种相关的优化建议。
- First Contentful Paint
- Time to Interactive
- Speed Index
- total Blocking Time
- Largest Contentful Paint
- Cumulative Layout Shift
每一项点开都会有更具体的优化策略,十分贴心。大家只需根据 Lighthouse 的建议进行优化即可。
三、CDN和Nginx开启HTTP/2
HTTP/2 的多路复用(Multiplexing)可以使用一个连接发起多个请求,在需要并发请求大量资源(JS/CSS/Images/…)的 Web 场景可以大幅缩短页面请求时长。
关于 HTTP/2 的直观效果大家可以参考一下Akamai这个demo。至于HTTP/2能否直接上线呢?可以参考 CanIUse.com,已经是非常成熟的技术了。
使用 wordpress.com 或其他平台服务提供的博客通常不需要管到这么具体的配置,自建站点如果使用了“各种面板”一般也会帮你打开。
手动安装部署 Nginx 的小伙伴可以看一下自己的 nginx conf 有没有开启 http2。
在 Linux 服务器上先找到自己博客域名的配置文件:
sudo vim /etc/nginx/sites-available/xxxx.com
也有可能在 sites-enabled
目录。
编辑域名配置文件,在 listen 后面加上 http2
即可:
listen 443 ssl http2;
编辑完记得 reload 一下:
sudo service nginx reload
除了站点配置之外,CDN 的配置也记得打开:
四、CDN和Nginx开启文本Gzip压缩
我们知道 html/js/css/json 都是纯文本资源,纯文本就存在压缩空间。现在 Gzip 压缩在各种主流浏览器已经非常普及了。所以我们可以在后台开启 Gzip 压缩支持,当客户端的 HTTP 请求头带有 Accept-Encoding: gzip
时,我们就可以返回使用 gzip 压缩过的包。可以参考 MDN 的文档: Accept-Encoding - HTTP | MDN
gzip 的原理很有意思,大致是利用了人类语言中的“重复性”,通过把重复的片段提取出来,以backpointers形式进行编码,然后再进行霍夫曼编码得出压缩后的文本,可以达到惊人的 70-90% 压缩率。也因此 gzip 对于不怎么具有重复性的二进制数据效果不佳,对于已经混淆压缩过的各种 .min.js
的效率也会低于原文:Optimizing Encoding and Transfer Size of Text-Based Assets
Joshua Davies的这篇长文 Dissecting the GZIP format 对Gzip算法进行非常详尽的解释,超级棒,有兴趣的小伙伴可以留言扣个 1 我有空可以翻译一下(挖坑小能手)。
总而言之言而总之,服务端开启 gzip 就完事了。
五、对图片资源进行处理
我们在 Web 中难免用到大量 jpg/png 格式的图片,所以第一步是确保上线前这些图片资源都经过合适的压缩。在保证图片质量的前提下尽量将体积压缩到最小。
最常使用到的服务无疑是 tinypng.com 啦。tinypng有开放 API,也有 Figma 插件,Wordpress 插件,免费额度已经非常足够,大家自行上官网取用即可。
压缩完图片之后我们还需要对 <img>
标签进行 Lazy Loading 懒加载优化。
浏览器的默认行为是解析完 DOM 发现有 <img>
就直接请求图片,即便这些图片并未被渲染在屏幕上。很多人进来看文章,还没看到图片就关掉页面了,这时候这些请求不仅导致浏览器体验不佳,还会浪费CDN流量。
现在大部份浏览器都支持 loading="lazy"
的写法,可以参考:Lazy loading - Web Performance | MDN 这篇文章。
如果嫌浏览器的行为不够激进的话,还可以使用Lozad.js这样的库实现更激进的图片懒加载。
六、使用WebP格式的图片取代jpg/png
Webp 是 Google 推出的一种图片格式,同等显示质量下,可比 PNG 小 26%,比JPEG 小 25-34%(参考这里)。
但并不是所有浏览器都支持 Webp,所以我们可以使用各种云服务提供的云端转码能力,当浏览器支持 Webp 时,向云端请求 Webp 格式的图片。
比如数据万象简介-腾讯云这样的接口,数据万象应该在国内各家云服务都有接口,大同小异,大家根据自己购买的云服务查看文档即可。
一般可在对应 CDN 的图片文件 URL 末尾拼接参数实现:
https://xxxx.png?imageMogr2/format/webp
具体支持的参数与收取费用大家查看文档即可。
七、缓存静态HTML
虽然我的博客是个“动态网站”,但我更新并不频繁,也没多少可实时变更的数据。所以大部份页面都可以在 PHP 输出一份静态 HTML 之后 Cache 起来。
我使用的是 WP Super Cache 这个插件,大家也可以使用其他的。
把服务器动态生成的静态 HTML 缓存减少服务端开销。我们近期发布的 《中文播客榜》xyzrank.com 直接就是个静态网站。反正数据更新只需要隔一段时间跑一次,没必要接服务端接口。
而且这样好处是永远不会Crash,哈哈哈。
八、What's Next?
本文总结的“老掉牙优化”技术就这么多了。我在六月份做博客优化的时候还没有想到会在七月份发布新站,结果这些东西立马就用上了。
刚刚翻我过去的文章,发现写 Typescript 是2020年,写 Vue 3 + Vite 是2021年,这些东西一开始折腾的时候都是痛并快乐着,现在都成了能用来实现各种想法的基础工具了。
我们播客的监控后台就是使用 ts + Express 做后端, Vue 3 + Vite 做前端实现的,Webpack 也没落下,用在了 xyzrank.com 这个公开项目上。
所以不断学习的感觉很棒,大家也不要觉得现在学一个什么东西可能没啥用,因为指不定哪天信手拈来就能做一个很好玩的东西了。
所以我前段时间在玩的 Golang 什么时候用上呢?🤔