Wagtail图片优化:静态与动态添加图片的优化方法
针对你提到的静态资源标签和Wagtail图片标签的加载场景,以下是可落地的优化方案:
一、优化Wagtail上传图片的渲染逻辑
Wagtail Images模块自带强大的图片处理能力,充分利用原生功能就能大幅降低图片体积:
放弃
original规格,生成适配尺寸的图片
你当前用{% image post.project_image original as pr_img %}加载原图,即使前端用CSS缩到290px,浏览器还是会下载完整的大尺寸图片。改成按渲染尺寸生成缩略图:{% image post.project_image fill-290x290 format-webp quality-80 as pr_img %} <img src="{{ pr_img.url }}" class="d-block mx-lg-auto img-fluid" alt="{{ post.title }}" width="290" height="290" loading="lazy">fill-290x290生成精确匹配容器尺寸的图片,format-webp强制用高压缩率的WebP格式,quality-80平衡画质和体积。用Picture标签实现多格式降级
为兼容不支持WebP的旧浏览器,用<picture>标签提供多种格式选项:{% image post.project_image fill-290x290 format-webp as webp_img %} {% image post.project_image fill-290x290 format-jpeg as jpeg_img %} <picture> <source srcset="{{ webp_img.url }}" type="image/webp"> <source srcset="{{ jpeg_img.url }}" type="image/jpeg"> <img src="{{ jpeg_img.url }}" alt="{{ post.title }}" width="290" height="290" loading="lazy"> </picture>预生成图片规格(Renditions)
在Page模型里定义常用的图片规格,让Wagtail在上传图片时自动生成,避免实时处理的性能开销:from wagtail.models import Page from wagtail.images.models import Rendition class ProjectPage(Page): # 原有字段... project_image = models.ForeignKey( 'wagtailimages.Image', null=True, blank=True, on_delete=models.SET_NULL, related_name='+' ) project_image_rendition = models.ForeignKey( Rendition, null=True, blank=True, on_delete=models.SET_NULL, related_name='+' ) def save(self, *args, **kwargs): if self.project_image: self.project_image_rendition = self.project_image.get_rendition('fill-290x290 format-webp') super().save(*args, **kwargs)模板里直接调用预生成的rendition:
<img src="{{ post.project_image_rendition.url }}" alt="{{ post.title }}" loading="lazy">
二、静态资源图片的优化
对于用{% static %}引入的图片,重点在预压缩和格式转换:
批量转换为WebP/AVIF格式
用Squoosh、ImageOptim等工具把所有静态PNG/JPG转成WebP(体积比JPG小50%左右),然后修改模板引用:<img class="zoom-fade" src="{% static 'images/project-elm/elm-1.webp' %}" alt="装饰图">背景图片用CSS的
image-set提供降级:.inner-hero { background-image: image-set( url('/static/images/banner_a/project_bg.webp') 1x, url('/static/images/banner_a/project_bg.png') 1x ); background-attachment: fixed; }合并小图为雪碧图
你页面里的elm-1.png、elm-2.png等装饰小图,可以合并成一张雪碧图,减少HTTP请求数。用工具生成雪碧图后,通过CSS定位显示:.left-bg-set img { width: 100px; height: 100px; background: url('{% static 'images/project-elm/sprite.webp' %}') 0 0 no-repeat; } .bottom-bg-set img { width: 80px; height: 80px; background: url('{% static 'images/project-elm/sprite.webp' %}') -100px 0 no-repeat; }
三、前端加载策略优化
背景图片懒加载
页面里的装饰背景图(比如sub-hero里的多个小图)可以用Intersection Observer实现懒加载,避免页面初始时加载所有图片:document.addEventListener('DOMContentLoaded', function() { const lazyBgElements = document.querySelectorAll('.bg-set-wrp div'); const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { const img = entry.target.querySelector('img'); img.src = img.dataset.src; // 把src放到data-src里,初始时不加载 observer.unobserve(entry.target); } }); }); lazyBgElements.forEach(el => observer.observe(el)); });模板里修改为:
<div class="left-bg-set"> <img class="zoom-fade" data-src="{% static 'images/project-elm/elm-1.webp' %}" alt="" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="> </div>添加低质量占位图(LQIP)
为Wagtail图片生成极小的占位图,提升用户感知加载速度:{% image post.project_image fill-20x20 format-jpeg quality-20 as lqip %} {% image post.project_image fill-290x290 format-webp as pr_img %} <img src="{{ pr_img.url }}" alt="{{ post.title }}" width="290" height="290" loading="lazy" style="background-image: url('{{ lqip.url }}'); background-size: cover;" >
四、服务器与缓存优化
- 开启CDN与浏览器缓存
把图片资源放到CDN上,同时配置Nginx/Apache的缓存头,让浏览器长期缓存图片:location ~* \.(webp|png|jpg|jpeg)$ { expires 1y; add_header Cache-Control "public, immutable"; } - 启用Brotli压缩
服务器开启Brotli压缩,对图片以外的静态资源(CSS/JS)进一步压缩,减少整体页面加载体积。
内容的提问来源于stack exchange,提问作者Imthiaz Muhassin

