图片优化:astro:assets
本教程共 56 篇 · 第 23 篇 · 更新于 2026-08-07 · 约 10 分钟阅读
本节目标:搞懂 Astro 怎么帮你自动处理图片,学完你能用 Image / Picture 组件压缩、转换图片格式,并理解本地、远程、public 三种图片来源的区别。
为什么要让框架管图片
一张没处理过的大图,会让网页变慢、用户等得心烦。图片优化(optimization)指的就是:把图片压小、转成更省流量的格式、并按屏幕大小提供合适尺寸。这些脏活累活,Astro 用一套叫 astro:assets 的内置能力替你包办了。
Note版本提醒:
astro:assets从 Astro 3 起就已经稳定。你可能在一些旧博客里看到它写着“experimental(实验性)”,那套说法早已过期,现在它是正式功能,放心用。
Astro 提供了两个内置组件 <Image /> 和 <Picture />,还有 Markdown 图片语法处理、SVG 组件、以及生成图片的函数。它们都会自动优化和转换图片。当然,你依然可以用原生 HTML 的 <img> 标签,只是那样 Astro 不会做任何处理。
图片该放哪儿:src 还是 public
这是新手第一个要搞清楚的问题。Astro 推荐把本地图片放进 src/(比如 src/assets/),因为放在这里的图片才会被 Astro 转换、优化、打包。而 public/ 目录里的文件是“原样拷贝”到线上、不做任何处理。
简单记:
- 想被优化 → 放
src/。 - 不想被处理、或要一个固定公开链接(比如网站图标 favicon)→ 放
public/。
远程图片(存在别的服务器或图床 CDN 上)则直接用完整网址。出于安全,Astro 默认只优化你“授权”的来源的图片,其他远程图只显示、不优化。
在 .astro 文件里用图片
.astro 文件里有几种选择:<Image />、<Picture />、原生 <img>、<svg>,以及把 SVG 当组件用。怎么写,取决于图片在哪:
---
import { Image } from 'astro:assets';
import localBirdImage from '../../images/subfolder/localBirdImage.png';
---
<!-- 本地图片:直接传 import 进来的对象 -->
<Image src={localBirdImage} alt="一只鸟坐在蛋巢上。" />
<!-- public/ 里的图片:用相对路径 -->
<Image src="/images/bird-in-public-folder.jpg" alt="一只鸟。" width="50" height="50" />
<!-- 远程图片:用完整网址,必须给宽高 -->
<Image src="https://example.com/remote-bird.jpg" alt="一只鸟。" width="50" height="50" />
<!-- 原生标签:不优化,原样输出 -->
<img src={localBirdImage.src} alt="一只鸟坐在蛋巢上。" />
注意区别:<Image /> 直接拿 import 对象(src={localBirdImage}),而原生 <img> 拿的是它的 .src 属性(src={localBirdImage.src})。
Image 组件:最常用的优化入口
<Image /> 用来显示优化后的图片,支持本地图和“已授权的远程图”。它会做这些事:
- 自动转成更高效的格式(如 WebP);
- 转换尺寸、格式、质量;
- 自动补上
alt、loading="lazy"(懒加载)、decoding="async"; - 自动推断宽高,避免页面“跳一下”(专业叫 CLS,累计布局偏移)。
用法里 alt 是必填项:
---
import { Image } from 'astro:assets';
import myImage from '../assets/my_image.png'; // 原图 1600x900
---
<Image src={myImage} alt="我的图片描述。" />
构建(预渲染)后,它实际生成的 <img> 大概长这样:
<img
src="/_astro/my_image.hash.webp"
width="1600"
height="900"
decoding="async"
loading="lazy"
alt="我的图片描述。"
/>
你可以给组件加 class,它会作用到最终生成的 <img> 上。若是按需渲染(on-demand rendering)模式,图片会在用户访问时实时生成,地址会变成一个端点链接。
指定质量与格式
默认情况下,Astro 会挑一个它认为合适的质量(通常足够清晰又够小)。如果你想自己拿捏,可以传 quality 和 format:
---
import { Image } from 'astro:assets';
import myImage from '../assets/my_image.png';
---
<!-- quality 用 0–100 的数字,越大越清晰也越大 -->
<Image src={myImage} alt="描述。" quality={80} />
<!-- format 直接指定输出格式 -->
<Image src={myImage} alt="描述。" format="png" />
<Image src={myImage} alt="描述。" format="webp" />
quality 不写时按 Astro 的默认策略;写了就听你的。format 则强制输出某种格式——但要注意:如果指定成浏览器不支持的格式,<Image /> 不会自动兜底,所以一般让它自动选,或跟 <Picture /> 配合给多种格式。
对远程图片还有个省心选项 inferSize:设成 true 后,Astro 会先去远程把图片下载下来、量出真实宽高,这样你就不用手动写 width/height:
<Image src="https://example.com/remote-bird.jpg" alt="一只鸟。" inferSize />
不过 inferSize 会在构建或请求时多一次网络往返,远程图特别多时要权衡。
Picture 组件:一份图多种格式
<Picture /> 从 Astro 3.3 起提供,它会生成一个 <picture> 标签,里面包含同一张图的不同格式和尺寸,浏览器按自身能力挑最合适的。比如同时给 avif 和 webp,再留一个 png 当兜底:
---
import { Picture } from 'astro:assets';
import myImage from '../assets/my_image.png';
---
<Picture src={myImage} formats={['avif', 'webp']} alt="我的图片描述。" />
生成的 HTML 会带多个 <source>,新浏览器吃 avif/webp(更小更清晰),老浏览器退回 png。和 <Image /> 一样,alt 必填。
响应式图片:让图跟着屏幕变
响应式(responsive)图片指图片能根据设备屏幕大小自动选尺寸,既清晰又不浪费流量。Astro 5.10 起,给 <Image /> 或 <Picture /> 加上 layout 属性,它就会自动生成 srcset 和 sizes,让图片随容器缩放:
<Image src={myImage} alt="描述。" layout='constrained' width={800} height={600} />
layout 有三种:constrained(限制最大宽度、可缩小)、full-width(占满整行)、fixed(固定尺寸)。想让全站图片默认都响应式,可以在 astro.config.mjs 里配 image.layout,这样连 Markdown 里的 ![]() 图片也会跟着变。
Tip想让响应式真正生效,最好在配置里打开
image.responsiveStyles: true。Astro 会注入少量全局样式保证图片正确缩放。如果你用 Tailwind 4 且想用自己的规则,可以保持默认false,用 Tailwind 的写法覆盖。
在 Markdown / MDX 里用图片
在 .md 文件里,直接写标准 Markdown 图片语法即可,本地图和远程图都会被优化:



但 public/ 里的图不会被优化。另外,Markdown 里不能用 <Image /> 和 <Picture /> 组件——它们只在 .astro 和 .mdx 里可用。如果你需要在 Markdown 体系里用组件级控制,建议改用 MDX(.mdx 文件),它在 .astro 用法基础上还支持标准 Markdown 语法混写。
远程图片要“授权”
为了安全,远程图片默认只显示不优化。想让 Astro 也帮你优化某来源的远程图,要在 astro.config.mjs 里登记域名或地址规则:
export default defineConfig({
image: {
domains: ["astro.build"], // 只优化来自 astro.build 的远程图
},
});
也可以用 remotePatterns 写更灵活的规则,比如“只允许 https 协议的图”:
export default defineConfig({
image: {
remotePatterns: [{ protocol: "https" }],
},
});
即使不授权、不优化,用 <Image /> 显示远程图依然能避免 CLS(布局抖动),这一点很值。
用 getImage() 在代码里生成图片
大多数时候你直接在模板里放 <Image /> 就够了。但当你需要把图片用在别处(比如 API 路由里拼一张图),可以用 getImage() 函数拿到优化后的图片信息:
---
import { getImage } from 'astro:assets';
import myBackground from '../background.png';
const optimizedBackground = await getImage({ src: myBackground, format: 'avif' });
---
<div id="background" data-src={optimizedBackground.src}></div>
注意 getImage() 只能在服务器端运行。要把结果用到浏览器端(比如客户端脚本里),就在脚本区先调用,再把 src 传下去。
别忘了 alt:无障碍很重要
不是所有用户都能“看见”图片,比如用读屏软件的人。alt 属性就是给图片写的文字说明,告诉读屏软件“这张图是什么”。<Image /> 和 <Picture /> 都强制要求写 alt,不写会报错提醒你。
如果图片纯粹是装饰(对理解页面没帮助),就写 alt="",读屏软件会知道忽略它。
图片服务与缓存
astro:assets 默认用 Sharp 这个图片引擎做转换。某些运行环境(如 Cloudflare)不支持 Sharp,可以改用“透传服务”(passthroughImageService),这时 Astro 不转换图片,但仍保留防 CLS、强制 alt 等好处。
构建时,Astro 会把处理过的图片缓存在 ./node_modules/.astro 里。下次构建复用缓存,省时间也省流量;远程图还会按对方服务器的缓存策略决定是否重新下载。
小结
本章我们认识了 astro:assets:本地图放 src/、原样文件放 public/、远程图用网址;用 <Image /> 做单图优化、<Picture /> 做多格式兜底;用 layout 实现响应式;远程图要授权才优化;alt 必写以保证无障碍。牢记——旧文说它“实验性”已过时,v3 起它就是稳定功能。下一章我们看文字的“字体”怎么自定义。