Skip to content

Commit ece4842

Browse files
committed
add post
1 parent fc67b4b commit ece4842

File tree

6 files changed

+169
-0
lines changed

6 files changed

+169
-0
lines changed
38.9 KB
Loading
183 KB
Loading
Lines changed: 10 additions & 0 deletions
Loading
171 KB
Loading
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
---
2+
title: "当Hugo遇上AVIF,加速图片加载"
3+
date: 2024-09-30T22:01:45+08:00
4+
draft: false
5+
tags:
6+
- 博客优化
7+
- hugo
8+
- avif
9+
- imagemagic
10+
- github
11+
---
12+
13+
![avif-on-hugo](avif-on-hugo.svg)
14+
15+
这篇文章会介绍基于Github Workflow使用ImageMagick生成AVIF图片,来优化Hugo站点的加载速度。
16+
17+
## 背景
18+
19+
AVIF是什么?
20+
21+
> AVIF(AV1 Image File Format)是一种基于AV1视频编码标准的图像文件格式。
22+
>
23+
> A modern image format based on the AV1 video format.
24+
>
25+
> AVIF generally has better compression than WebP, JPEG, PNG and GIF and is designed to supersede them.
26+
27+
![browser support avif](support.png)
28+
29+
在2024年,绝大部分浏览器都已经支持了AVIF格式。
30+
31+
ImageMagick是什么?
32+
33+
> ImageMagick® is a free, open-source software suite, used for editing and manipulating digital images.
34+
>
35+
> It can be used to create, edit, compose, or convert bitmap images, and supports a wide range of file formats, including JPEG, PNG, GIF, TIFF, and Ultra HDR.
36+
37+
ImageMagick是一款用于图像处理的一个工具。
38+
39+
## 对比
40+
41+
AVIF说的这么好,我们来验证对比一下。
42+
43+
对于一张PNG的图片,使用ImageMagick分别生成WEBP和AVIF格式的图片,文件大小如下:
44+
45+
```
46+
-rw-r--r--@ 1 liudon staff 1.1M 9 29 23:02 20240922-170856.png
47+
-rw-r--r--@ 1 liudon staff 15K 9 29 23:08 20240922-170856.png.avif
48+
-rw-r--r--@ 1 liudon staff 25K 9 29 23:07 20240922-170856.png.webp
49+
```
50+
51+
WEBP比PNG要节省90%左右,AVIF要比WEBP再小40%左右。
52+
53+
效果出奇的好,开搞吧。
54+
55+
## 使用
56+
57+
### 1. 生成AVIF文件
58+
59+
博客使用了Github Workflow来进行部署,所以生成ImageMagick的工作也就放在了Github Workflow上。
60+
61+
```
62+
- name: Compress Image
63+
run: |
64+
sudo apt-get update
65+
sudo apt-get install -y imagemagick libheif-dev
66+
find ./content/posts/ -type f \( -name "*.jpg" -o -name "*.png" -o -name "*.jpeg" \) -exec convert {} -resize 1080x\> -quality 75 -define webp:image-hint=photo {}_1080x.webp \;
67+
find ./content/posts/ -type f \( -name "*.jpg" -o -name "*.png" -o -name "*.jpeg" \) -exec convert {} -resize 1080x\> {}_1080x.avif \;
68+
```
69+
70+
新增压缩图片步骤,同时生成WEBP和AVIF格式文件。
71+
72+
含义说明,可以自行调整:
73+
74+
```
75+
-resize 1080x> 表示缩放到1080宽,>表示只有在原图宽大于1080时才进行缩放,小于不做处理。
76+
-quality 75 表示处理后图片质量,值越小图越小,图片也越不清晰。
77+
-define webp:image-hint=photo 这里是为了对齐Hugo自身的图片处理参数。
78+
```
79+
80+
### 2. 使用AVIF文件
81+
82+
修改`layouts/_default/_markup/render-image.html`文件:
83+
84+
```
85+
{{- $respSizes := slice 1080 -}}
86+
{{- $dataSizes := "(min-width: 768px) 1080px, 100vw" -}}
87+
88+
{{- $holder := "GIP" -}}
89+
{{- $hint := "photo" -}}
90+
{{- $filter := "box" -}}
91+
92+
{{- $Destination := .Destination -}}
93+
{{- $Page := .Page -}}
94+
{{- $Text := .Text -}}
95+
{{- $Title := .Title -}}
96+
97+
{{- $responsiveImages := (.Page.Params.responsiveImages | default site.Params.responsiveImages) | default true }}
98+
99+
{{ with $src := .Page.Resources.GetMatch .Destination }}
100+
{{- if $responsiveImages -}}
101+
{{- $imageTypes := slice -}}
102+
{{- if and hugo.IsExtended (ne $src.MediaType.Type "image/webp") -}}
103+
{{- $imageTypes = $imageTypes | append "avif" -}} <!-- avif need the first -->
104+
{{- $imageTypes = $imageTypes | append "webp" -}}
105+
{{- end -}}
106+
{{- if gt (index $respSizes 0) $src.Width -}}
107+
{{- $respSizes = slice $src.Width -}}
108+
{{- end -}}
109+
<picture>
110+
{{- range $imageType := $imageTypes -}}
111+
<source type="image/{{ $imageType }}" srcset="
112+
{{- $compressedImage := printf "%s_1080x.%s" $Destination $imageType -}}
113+
{{- $cmSrc := $Page.Resources.GetMatch $compressedImage -}}
114+
{{- if $cmSrc -}}
115+
<!--avif/webp file exist-->
116+
{{ $cmSrc.RelPermalink | absURL}} 1080w
117+
{{- else -}}
118+
<!-- hugo not support avif format -->
119+
{{ if ne $imageType "avif" }}
120+
{{- with $respSizes -}}
121+
{{- range $i, $e := . -}}
122+
{{- if ge $src.Width . -}}
123+
{{- if $i }}, {{ end -}}{{- ($src.Resize (print . "x " $imageType " " $filter) ).RelPermalink | absURL}} {{ . }}w
124+
{{- end -}}
125+
{{- end -}}
126+
{{- end -}}
127+
{{ end }}
128+
{{- end -}}" sizes="{{ $dataSizes }}" />
129+
{{- end -}}
130+
<img src="{{ $Destination | safeURL }}" width="{{ .Width }}" height="{{ .Height }}" alt="{{ $Text }}" title="{{ $Title }}" loading="lazy" />
131+
</picture>
132+
{{- else }}
133+
<img src="{{ $Destination | safeURL }}" width="{{ $src.Width }}" height="{{ $src.Height }}" alt="{{ $Text }}" title="{{ $Title }}" loading="lazy" />
134+
{{- end }}
135+
{{ end }}
136+
```
137+
138+
这里如果AVIF/WEBP文件已经存在,那么直接使用对应文件(注意:我这里都是生成的1080宽,如果你有调整记得一起调整);
139+
140+
否则会使用Hugo自身的Image Processing生成对应格式文件。
141+
142+
## 效果
143+
144+
优化前:
145+
146+
![optimize before](before.jpg)
147+
148+
优化后:
149+
150+
![optimize after](after.jpg)
151+
152+
从WEBP切换到AVIF,文件大小减少了30%左右。
153+
154+
哈哈,太棒了,效果杠杠滴。
155+
156+
唯一的缺点就是每次都是全量生成图片,Workflow执行略久些(我的要5分钟左右),这里后面再优化。
157+
158+
从23年11月开始有的想法,在24年9月最后一天终于实现了。🎉🎉🎉
159+
407 KB
Loading

0 commit comments

Comments
 (0)