Next.js <Image>组件输出JPG而非WebP/AVIF格式问题问询
你配置了formats: ['image/avif', 'image/webp']但输出始终是JPG,核心原因是自定义loader会完全绕过Next.js内置的图片优化链路。
Next.js自动协商返回AVIF/WebP格式、自动转码压缩的能力,仅在使用默认内置loader、走框架自带的/_next/image优化接口时生效。一旦传入自定义loader,next/image只会严格按照你写的逻辑拼接图片地址,不会触发任何内置的格式转换逻辑,next.config.js里的formats配置对自定义loader完全无效。
你当前对接的是Sanity CDN,现有loader只拼接了宽度、质量参数,没有指定输出格式,CDN默认就会返回原格式JPG。
二选一即可:
方案1:移除自定义loader,使用Next.js内置优化
你已经将cdn.sanity.io加入了图片域名白名单,直接删掉Image组件上的loader={myLoader}属性即可。
此时Next.js会自动拉取Sanity源图,根据浏览器请求头里的支持格式标识,优先返回AVIF、WebP格式,你写的formats配置会正常生效。
注意如果是自部署Next.js服务,需要提前安装sharp依赖,否则内置图片优化功能无法正常运行;Vercel等官方托管平台默认已经预装该依赖,无需额外配置。
方案2:保留自定义loader,对接Sanity CDN的自动格式能力
如果不想占用Next.js服务端的优化算力,想直接走Sanity CDN的图片处理能力,只需要修改现有loader,加上Sanity自带的自动格式参数即可:
const myLoader = ({ src, width, quality }) => { return `${src}?w=${width}&q=${quality || 85}&auto=format` }
加了&auto=format参数后,Sanity CDN会自动识别请求端支持的图片格式,优先返回AVIF/WebP,不需要额外写前端格式判断逻辑。
- 本地开发环境的图片优化逻辑和生产环境不完全一致,不要在dev模式下验证格式输出,执行
next build && next start跑生产环境验证结果最准确 - Next.js内置图片优化默认限制单张源图大小为10MB,超过阈值会抛错,大尺寸图片建议提前在Sanity侧做裁剪压缩
- 如果你使用广告拦截类浏览器插件,有可能会修改请求头导致格式协商失效,排查时可以先禁用插件测试
内容的提问来源于stack exchange,提问作者Enadot

