6

我的网页加载速度优化:看似无用所学,终有用武之地

 2 years ago
source link: https://justinyan.me/post/5046
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
我的博客加载速度优化:看似无用所学,终有用武之地

前段时间给我的博客做了一下加载速度优化,同事笑称我的“优化”都是好几百年前的技术了😂。不过我很多年没有认真做前端了,这个博客 justinyan.me 搬过几次Server,但一直用的是Wordpress,接入是Nginx。除了最近两年把图片搬到腾讯云CDN之外就没做过什么优化,也难怪要被同事嘲笑。

以下是我对这个陈年老博客做过的优化,有些是之前做过的,记录一下供以后参考。这些想必早成前端基础,专业人士莫笑。😁

P.S. 这篇文章是6月份开始写的,7月18日我们发布了《中文播客榜》xyzrank.com也用上了了所有的优化,现在想来,技术的东西总是一开始折腾,后来就成为下一个项目的基础了。

一、把静态资源搬到CDN

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

webpack config content hash

原理是为正式环境编译文件时,根据文件内容计算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找出优化点

lighthouse

刚开始工作的时候我针对公司项目一个大文件读取进行了优化,因为读取量是以前的三分之一,所以我当时跟我的 Leader 说我的优化效果理论上可减少三分之二的耗时,性能提升三倍。我的 Leader 跟我说,优化必须要有数据,不能靠猜,所以需要跑一下 Profile 来证明我的结论。

自那以后我就记得,一切优化必须有数据做支撑,否则你也许做了负优化都未可知。

前端的优化工具很多,Chrome 自带的 Dev Tools 里就有个超好用的 Lighthouse 工具,可以帮我们分析出当前页面存在的问题。Lighthouse分为几个大项:

  1. Performance
  2. Accessibility
  3. Best pratices
  4. Progressive Web App

为了减少缓存优化带来的误判,建议在“隐身模式”(Incognito)下运行。跑完一次分析之后,工具会给出各种相关的优化建议。

  1. First Contentful Paint
  2. Time to Interactive
  3. Speed Index
  4. total Blocking Time
  5. Largest Contentful Paint
  6. Cumulative Layout Shift

每一项点开都会有更具体的优化策略,十分贴心。大家只需根据 Lighthouse 的建议进行优化即可。

三、CDN和Nginx开启HTTP/2

http2-nginx

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压缩

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 就完事了。

五、对图片资源进行处理

tinypng

我们在 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 format

Webp 是 Google 推出的一种图片格式,同等显示质量下,可比 PNG 小 26%,比JPEG 小 25-34%(参考这里)。

并不是所有浏览器都支持 Webp,所以我们可以使用各种云服务提供的云端转码能力,当浏览器支持 Webp 时,向云端请求 Webp 格式的图片。

比如数据万象简介-腾讯云这样的接口,数据万象应该在国内各家云服务都有接口,大同小异,大家根据自己购买的云服务查看文档即可。

一般可在对应 CDN 的图片文件 URL 末尾拼接参数实现:

https://xxxx.png?imageMogr2/format/webp

具体支持的参数与收取费用大家查看文档即可。

七、缓存静态HTML

html cache

虽然我的博客是个“动态网站”,但我更新并不频繁,也没多少可实时变更的数据。所以大部份页面都可以在 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 什么时候用上呢?🤔


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK