Angular 10中如何将任意格式图片转为压缩AVIF格式展示
Angular 10 页面加载AVIF压缩图实现方案
注意:不要尝试在前端运行时做图片格式转码,客户端转AVIF会占用大量用户设备CPU、内存资源,转码等待时间长,完全违背压缩图片提升加载速度的初衷,最优实现路径是服务端预生成AVIF资源+前端做兼容适配
第一步:提前准备AVIF资源
- 对存量的jpeg/png/webp原图做批量转码,生成同文件名的.avif版本,压缩质量参数建议设为60-70,同主观画质下AVIF体积比WebP小30%以上,原本5MB的原图基本可以压缩到1MB以内
- 资源路径和原图保持映射关系即可,比如原图路径
/imgs/demoImage.jpeg对应AVIF路径为/imgs/demoImage.avif,不需要修改数据库中原有存储的原图路径字段 - 给上传流程加自动转码逻辑,后续新上传的图片自动生成对应AVIF副本,不需要手动维护
第二步:Angular 侧适配实现
这套逻辑不需要安装任何第三方依赖,利用原生HTML特性即可实现,Angular 10全版本兼容。
核心实现:用picture标签做兼容降级
直接用原生<picture>标签做格式优先级判断,支持AVIF的浏览器会优先加载AVIF资源,不支持的浏览器自动回退加载原有格式的原图,不会出现裂图问题。
组件模板代码示例:
<picture> <!-- 优先加载AVIF压缩资源 --> <source srcset="{{avifPath}}" type="image/avif"> <!-- 不支持AVIF的浏览器匹配原有格式资源 --> <source srcset="{{originalImgPath}}" type="{{originalMimeType}}"> <!-- 兜底img标签,所有浏览器均可识别 --> <img [src]="currentRenderSrc" [alt]="imgAlt" loading="lazy" (error)="handleImgError()" > </picture>
对应组件类中的逻辑:
import { Component, Input, OnInit } from '@angular/core'; @Component({ selector: 'app-avif-img', templateUrl: './avif-img.component.html' }) export class AvifImgComponent implements OnInit { // 业务侧传入原有数据库存储的图片路径即可,不需要改现有业务传参 @Input() originalImgPath: string; @Input() imgAlt: string = ''; currentRenderSrc: string; ngOnInit() { this.currentRenderSrc = this.avifPath; } // 自动替换后缀生成AVIF路径 get avifPath(): string { return this.originalImgPath.replace(/\.(jpe?g|png|webp)$/i, '.avif'); } // 获取原图片的MIME类型,供source标签匹配 get originalMimeType(): string { const ext = this.originalImgPath.split('.').pop()?.toLowerCase(); const mimeMap = { jpg: 'image/jpeg', jpeg: 'image/jpeg', png: 'image/png', webp: 'image/webp' }; return mimeMap[ext] || 'image/jpeg'; } // 图片加载失败兜底:AVIF不存在/加载失败时自动切回原图 handleImgError() { if (this.currentRenderSrc !== this.originalImgPath) { this.currentRenderSrc = this.originalImgPath; } } }
使用方式
封装成公共组件后,业务侧和原来用img标签的逻辑完全一致,直接传入原图片路径即可:
<app-avif-img [originalImgPath]="'https://你的资源域名/imgs/demoImage.jpeg'" [imgAlt]="'示例图片'" ></app-avif-img>
避坑说明
- 不要直接把img标签的src硬改成AVIF路径:Safari 15.4以下版本、IE全版本等老旧浏览器不支持AVIF格式,直接改src会出现裂图
- 不要在前端用JS/WASM运行时转码:单张5MB的图前端转码需要数百毫秒到数秒,低端移动设备可能直接卡死页面,转码消耗的性能、时间远大于加载AVIF节省的成本,没有实际收益
- 可以给img标签统一加
loading="lazy"做懒加载,进一步减少首屏加载的资源体积
内容的提问来源于stack exchange,提问作者John Mark
相关产品推荐
相关产品推荐

