拥抱AVIF:提升网站加载速度的最佳实践,附Zola模板

简介: AVIF(AV1图像文件格式)是一种高效、开源且免版税的图片格式,相比JPG和PNG,在视觉相似的压缩水平下,文件大小可减少50%。它支持有损与无损压缩、动画存储、Alpha通道、HDR及宽色域等特性。2024年起,现代浏览器已全面支持AVIF。通过使用HTML `<picture>`标签,可优先加载AVIF图片,同时兼容WebP格式,提升网站性能与用户体验。本文还分享了在Zola静态网站生成器中实现AVIF支持的方法,大幅降低图片文件体积,优化带宽与流量成本,实现技术升级与用户需求的双赢。

背景

互联网已经悄然成为了大多数人生活中的一部分,从互联网获取信息的效率甚至开始逐渐影响生活品质。而决定或许信息效率的,很大程度上是图片、视频、音频这类文件大、传输久的多媒体资源,如果一张图片经过数秒都没有显示出来,用户心理就会逐渐烦躁。

为了提高互联网的使用体验,互联网基础设施近年来飞速发展,运营商不断提高家用带宽,云服务商也在不断提高存储空间和运行速度。

与此同时,互联网的应用技术也在飞速发展,AVIF 图片格式就是一种新的降低图片大小的技术。

AVIF的优势

AVIF(AV1 图像文件格式)是一种功能强大、开源、免版税的文件格式,它在高效图像文件格式(HEIF)容器中对 AV1 比特流进行编码。

AVIF 的优势主要有:

  • 与 JPG 和 PNG 相比,在视觉上相似的压缩水平下,有损压缩效果极佳(例如,有损 AVIF 图像比 JPEG 图像小 50%)。

  • 一般来说,AVIF 比 WebP 有更好的压缩效果。对于相同的 JPG 图像集,中值压缩率为 50%,而 WebP 为 30%。

  • 支持无损压缩。注意:AVIF 有损压缩效果最好,无损压缩非常糟糕。

  • 动画/多图像存储(类似于 GIF 动画,但压缩效果更好)

  • 支持 Alpha 通道(类似 PNG 的透明效果)。

  • 高动态范围(HDR):支持存储图像,使图像最亮和最暗部分之间的对比度更大。

  • 宽色域:支持包含更大色彩范围的图像

AVIF的兼容性

2024年1月起,所有现代浏览器内核均原生支持了 AVIF 格式,具体的兼容情况如下表。

图片

AVIF 格式浏览器支持情况

为网站添加AVIF支持

将现有网站进行改造,需要使用<picture>标签,原理是让 AVIF 图片拥有更高的加载优先级,同时让 WebP 图片成为默认选项,以使用浏览器不支持 AVIF 格式或者不支持<picture>的场景。

实现步骤

  • 生成AVIF格式的静态图片资源

  • 使用<picture>迭代网站代码,实现优先使用AVIF图片资源

  • 以 WebP 图片资源作为备用格式,以支持所有现代浏览器

HTML示例

为了同时提供AVIF和 WebP 格式的图片,并优先选择AVIF图片,HTML示例如下:

单张图片示例

<picture>
    <source media="(min-width: 1em)"
        srcset="https://blog.jiaxiang.wang/processed_images/wangjiaxiang.3ffc49360b8d0f4a.avif">
    <img decoding="async" loading="lazy"
        src="https://blog.jiaxiang.wang/processed_images/wangjiaxiang.9da683e50cd9e8e3.webp">
    <noscript>
        <img decoding=async loading=lazy
            src=https://blog.jiaxiang.wang/processed_images/wangjiaxiang.9da683e50cd9e8e3.webp>
    </noscript>
</picture>

自适应图片示例

<picture>
    <source media="(min-width: 75em)"
        srcset="https://blog.jiaxiang.wang/processed_images/cover.c9f41150d42dd922.avif?w=75em">
    <source media="(min-width: 60em)"
        srcset="https://blog.jiaxiang.wang/processed_images/cover.8a5702f3a8e70894.avif?w=60em">
    <source media="(min-width: 45em)"
        srcset="https://blog.jiaxiang.wang/processed_images/cover.7c77c39bd9c4aecf.avif?w=45em">
    <source media="(min-width: 30em)"
        srcset="https://blog.jiaxiang.wang/processed_images/cover.84260927604003ae.avif?w=30em">
    <source media="(min-width: 22em)"
        srcset="https://blog.jiaxiang.wang/processed_images/cover.bf6fed3bb08dc5b6.avif?w=22em">
    <img alt="post cover" 
        src="https://blog.jiaxiang.wang/processed_images/cover.f87982a6a8f5deec.webp?w=30em"
        srcset="https://blog.jiaxiang.wang/processed_images/cover.44069ef9d602bba4.webp?w=22em 360w,
              https://blog.jiaxiang.wang/processed_images/cover.f87982a6a8f5deec.webp?w=30em 500w,
              https://blog.jiaxiang.wang/processed_images/cover.aaa31e1b305b4c76.webp?w=45em 720w,
              https://blog.jiaxiang.wang/processed_images/cover.035a2838bfa48308.webp?w=60em 960w,
              https://blog.jiaxiang.wang/processed_images/cover.381457d3266f39c4.webp?w=75em 1200w"
        decoding="async" loading="lazy">
    <noscript>
        <img alt="post cover" src="https://blog.jiaxiang.wang/processed_images/cover.f87982a6a8f5deec.webp?w=30em"
            decoding=async loading=lazy>
    </noscript>
</picture>

Zola示例

我的博客使用 Zola 框架构建,使用我的开源主题 zola-theme-jiaxiang.wang,其实,Zola 本身提供图片处理的高级功能,但并不支持生成AVIF。为了实现拥抱AVIF,我通过 PR 向官方贡献了AVIF支持的功能,并在Zola的0.20.0版本中被合并,开源主题也在最新版本中同步添加了支持生成AVIF图片。

下面分享一下如何在Zola的主题模板中如何添加支持,各位可以根据需求进行修改。

生成自定义尺寸与格式缩略图

首先,需要定义一个模板宏,用于封装Zola的图片处理高级功能resize_image(),在后面会被用到。

{# 生成缩略图,跳过avif格式和svg格式 #}
{% macro thumbnail(url, width=800, height=500, op="fit", quality=75, format="webp") %}
{%- if url is ending_with(".avif") or url is ending_with(".svg") -%}
    {
  { url | trim | safe }}
{%- else -%}
    {%- if url -%}
        {%- if format == "avif" -%}
            {%- if not config.extra.other.avif_enable -%}
                {%- set format = "webp" -%}
            {%- else -%}
                {%- set quality = 50 -%}
            {%- endif -%}
        {%- endif -%}
        {%- set thumbnail = resize_image(path=url | trim, width=width, height=height, op=op, format=format, quality=quality) -%}
        {%- set result = thumbnail.url -%}
    {%- else -%}
        {%- set result = config.extra.site.default_cover -%}
    {%- endif -%}
    {
  { result | trim | safe }}
{%- endif -%}
{% endmacro %}

单张图片示例

定义模板宏,用于加载图片,不改变图片尺寸,仅添加 AVIF 支持。逻辑是优先加载 AVIF,同时提供 WebP 备选。

注意的是必须提供src参数用于加载图片。

{# 功能:加载图片,优先加载 AVIF,提供 WebP 备选 #}
{# 参数(必需):src 图片本地路径 #}
{# 参数:alt 图片 alt 文本 #}
{# 参数:id 图片 id #}
{# 参数:class 图片 class #}
{# 参数:style 图片 style #}
{# 参数:onclick 图片 onclick 事件#}
{% macro loading_img_single_size(src, alt="", id="", class="", style="", onclick="") %}
<picture {% if id != "" %}id="{
  { id }}" {% endif %}
    {% if class != "" %}class="{
  { class }}"{% endif %}
    {% if style != "" %} style="{
  { style }}"{% endif %}
    {% if onclick != "" %} onclick="{
  { onclick }}"{% endif %}>
    {#- avif image -#}
    <source media="(min-width: 1em)" srcset="{
  { macro::thumbnail(url=src, format="avif") | trim | safe }}" />
    {#- webp image -#}
    <img {% if alt != "" %}alt="{
  { alt }}"{% endif %}
        loading="lazy" decoding="async"
        src="{
  { macro::thumbnail(url=src, format="webp") | trim | safe }}"/>
    {#- a noscript fallback -#}
    <noscript>
        <img loading="lazy" decoding="async"{% if alt != "" %} alt="{
  { alt }}"{% endif %}
            src="{
  { macro::thumbnail(url=src, format="webp") | trim | safe }}">
    </noscript>
</picture>
{% endmacro %}

使用起来就比较方便了,例如加载图片封面只需要调用函数即可

{% import "_macros.html" as macro %}

……

<div>
    {
  { macro::loading_img_single_size(src=post.extra.cover), class="post-cover" }}
</div>
……

自适应图片示例

在网站中,图片加载的最佳实践是根据不同屏幕尺寸使用不同大小的图片,这里提供一个简单示例,可以根据自己的需求修改。

定义模板宏,用于根据显示器分辨率自适应加载图片。逻辑是优先加载 AVIF,同时提供 WebP 备选。和单张图片加载的区别是在sourcesrc-set中加入了不同分辨率的图片路径。

注意的是必须提供src参数用于加载图片。

{# 功能:根据显示器分辨率自适应加载图片,优先加载 AVIF,提供 WebP 备选 src 本地路径,无尺寸自适应,用于提供avif和webp支持 #}
{# 参数(必须):src 图片本地路径 #}
{# 参数:alt 图片 alt 文本 #}
{# 参数:id 图片 id #}
{# 参数:class 图片 class #}
{# 参数:style 图片 style #}
{# 参数:onclick 图片 onclick 事件#}
{% macro loading_img_multiple_size(src, alt="", id="", class="", style="", onclick="") %}
<picture {% if id != "" %}id="{
  { id }}" {% endif %}
    {% if class != "" %}class="{
  { class }}"{% endif %}
    {% if style != "" %} style="{
  { style }}"{% endif %}
    {% if onclick != "" %} onclick="{
  { onclick }}"{% endif %}>
    {#- avif image -#}
    {#- 75em = 1200px -#}
    <source media="(min-width: 75em)" srcset="{
  { macro::thumbnail(url=src, width=1200, op="fit_width", format="avif") | trim | safe }}?w=75em" />
    {#- 60em = 960px -#}
    <source media="(min-width: 60em)" srcset="{
  { macro::thumbnail(url=src, width=960, op="fit_width", format="avif") | trim | safe }}?w=60em" />
    {#- 45em = 720px -#}
    <source media="(min-width: 45em)" srcset="{
  { macro::thumbnail(url=src, width=720, op="fit_width", format="avif") | trim | safe }}?w=45em" />
    {#- 30em = 500px -#}
    <source media="(min-width: 30em)" srcset="{
  { macro::thumbnail(url=src, width=500, op="fit_width", format="avif") | trim | safe }}?w=30em" />
    {#- 22em = 360px -#}
    <source media="(min-width: 22em)" srcset="{
  { macro::thumbnail(url=src, width=360, op="fit_width", format="avif") | trim | safe }}?w=22em" />
    {#- webp image -#}
    <img {% ifalt != "" %}alt="{
  { alt }}"{% endif %}
        loading="lazy"decoding="async"
        src="{
  { macro::thumbnail(url=src, width=500, op="fit_width", format="webp") | trim | safe }}?w=30em"
        srcset="{
  { macro::thumbnail(url=src, width=360, op="fit_width", format="webp") | trim | safe }}?w=22em360w,
            {
  { macro::thumbnail(url=src,width=500,op="fit_width", format="webp") | trim | safe }}?w=30em500w,
            {
  { macro::thumbnail(url=src,width=720,op="fit_width", format="webp") | trim | safe }}?w=45em720w,
            {
  { macro::thumbnail(url=src,width=960,op="fit_width", format="webp") | trim | safe }}?w=60em960w,
            {
  { macro::thumbnail(url=src,width=1200,op="fit_width", format="webp") | trim | safe }}?w=75em1200w"/>
    {#- a noscript fallback -#}
    <noscript>
        <img loading="lazy" decoding="async"{% if alt != "" %} alt="{
  { alt }}"{% endif %}
            src="{
  { macro::thumbnail(url=src, width=500, op="fit_width", format="webp") | trim | safe }}?w=30em">
    </noscript>
</picture>
{% endmacro %}

使用方式和单张图片类似,只需要调用函数即可

{% import "_macros.html" as macro %}

……

<div>
    {
  { macro::loading_img_multiple_size(src=post.extra.cover), class="post-cover" }}
</div>
……

总结

本文介绍了 AVIF 图片格式的优势,通过大幅降低图片文件的大小,能极大提高网站访问速度,并大幅降低对带宽的需求和流量成本,是让用户和网站双赢的一种技术!

通过引入AVIF格式,使得本博客中型尺寸图片(800x500像素)的平均大小从200kb降低到20kb。并且,本博客在引入新技术的同时,还保留了对 WebP 格式的支持,这样能够在较早期的设备上正常显示,做到最广的兼容性。

当然,图片的相关技术仍在不断发展,或许将来会出现更加高效的图片格式,一起拭目以待吧~

目录
相关文章
|
定位技术
Mac电脑报错“托管配置文件格式不正确”的解决方法
Mac电脑报错“托管配置文件格式不正确”的解决方法
1144 1
|
人工智能 自然语言处理 前端开发
产品经理也能“开发”需求?淘宝信息流从需求到上线的AI端到端实践
淘宝推荐信息流业务,常年被“需求多、技术栈杂、协作慢”困扰,需求上线周期动辄一周。WaterFlow——一套 AI 驱动的端到端开发新实践,让部分需求两天内上线,甚至产品经理也能“自产自销”需求。短短数月,已落地 30+ 需求、自动生成 5.4 万行代码,大幅提升研发效率。接下来,我们将揭秘它是如何落地并改变协作模式的。
417 37
产品经理也能“开发”需求?淘宝信息流从需求到上线的AI端到端实践
|
7月前
|
人工智能 小程序 计算机视觉
AI不只有大模型,小模型也蕴含着大生产力
近年来,AI大模型蓬勃发展,从ChatGPT掀起全球热潮,到国内“百模大战”爆发,再到DeepSeek打破算力壁垒,AI技术不断刷新认知。然而,在大模型备受关注的同时,许多小而精的细分模型却被忽视。这些轻量级模型无需依赖强大算力,可运行于手机、手持设备等边缘终端,广泛应用于物体识别、条码扫描、人体骨骼检测等领域。例如,通过人体识别模型衍生出的运动与姿态识别能力,已在AI体育、康复训练、线上赛事等场景中展现出巨大潜力,大幅提升了相关领域的效率与应用范围。本文将带您深入了解这些高效的小模型及其实际价值。
|
PHP 计算机视觉 开发者
PHP中的图像处理:GD库与Imagick的应用比较
在PHP开发中,图像处理是一个常见的需求,尤其是在开发图像生成、编辑、缩放等功能时。PHP提供了两种主流的图像处理库——GD库和Imagick,它们各自具有不同的特点和适用场景。本文将对这两者进行比较,帮助开发者根据项目需求选择合适的图像处理工具。
|
数据库管理
Mac检出svn checkout报错 svn: E200030: SQLite 编译为 3.39.5,但是运行于 3.39.4
Mac检出svn checkout报错 svn: E200030: SQLite 编译为 3.39.5,但是运行于 3.39.4
736 0
|
JavaScript
JS【详解】setTimeout 延时(含清除 setTimeout,计时开始时间,0 秒延时解析,多 setTimeout 执行顺序,setTimeout 应用场景,网红面试题)
JS【详解】setTimeout 延时(含清除 setTimeout,计时开始时间,0 秒延时解析,多 setTimeout 执行顺序,setTimeout 应用场景,网红面试题)
2859 0
|
SQL Oracle 关系型数据库
Oracle rman备份保留策略,归档删除策略及delete命令的使用
oracle rman备份保留策略、归档策略的使用及对delete命令的影响
2599 0
使用Python编写一个多线程的12306抢票程序
使用Python编写一个多线程的12306抢票程序
|
机器学习/深度学习 资源调度
深度学习基础入门篇[四]:激活函数介绍:tanh、sigmoid、ReLU、PReLU、ELU、softplus、softmax、swish等
深度学习基础入门篇[四]:激活函数介绍:tanh、sigmoid、ReLU、PReLU、ELU、softplus、softmax、swish等
深度学习基础入门篇[四]:激活函数介绍:tanh、sigmoid、ReLU、PReLU、ELU、softplus、softmax、swish等
|
搜索推荐 定位技术 vr&ar
探索未来教育:“虚拟现实(VR)”在教育与培训中的创新应用
传统教育模式面临着许多挑战,而虚拟现实(VR)技术为教育带来了全新的可能性。本文将深入探讨VR在教育与培训领域的应用,包括虚拟实景教学、远程协作学习以及个性化教育等方面的创新。通过VR技术的引入,我们可以为学生提供身临其境的学习体验,提高学习效果,培养创造力和解决问题的能力。