813 字
4 分钟
在 Astro 中实现全自动响应式图像:结合 Rehype 与 astro:assets
在 Astro 中实现全自动响应式图像处理的优雅方案。通过编写一个自定义 Rehype 插件,在构建时拦截 Markdown 图片,并利用 astro:assets 的强大功能将其替换为高性能的响应式组件

背景
在 70c1a207a437b3a7ca74faf16563f7a8abf2dcfe
这次提交中,博客的图像处理能力得到了质的飞跃。其核心目标是:在不改变 Markdown 写作习惯(即仍然使用 
语法)的前提下,自动将标准图片转换为功能强大的响应式图像。
这解决了传统 <img>
标签的几个痛点:无法根据设备尺寸提供不同大小的图片、无法自动转换为 WebP 等现代格式、以及需要手动添加懒加载等。
实现方案
该方案巧妙地结合了 Astro 的构建时转换能力和组件化能力,主要分为两步:
1. 使用 Rehype 插件拦截图像
第一步是在内容处理流程中,找到所有的 <img>
标签并将其替换为一个自定义的 Astro 组件。这通过一个自定义的 Rehype 插件 rehype-figure.mjs
来实现。
它的工作流程如下:
- 遍历 AST:插件遍历由 Markdown 生成的 HTML 抽象语法树(AST)。
- 定位
<img>
:找到所有标签名为img
的节点。 - 创建新节点:提取出原
<img>
标签的src
和alt
属性。 - 替换节点:使用这些属性创建一个新的
<markdown-image>
组件节点,并用它替换掉原来的<img>
节点。
import { visit } from 'unist-util-visit';import { h } from 'hastscript';
export default function rehypeFigure() { return (tree) => { visit(tree, 'element', (node, index, parent) => { if (node.tagName !== 'img') return;
const src = node.properties?.src; const alt = node.properties?.alt; if (!src) return;
// 创建 <markdown-image> 组件节点 const markdownImageNode = h('markdown-image', { src, alt: alt || '' });
// 替换 if (parent && typeof index === 'number') { parent.children[index] = markdownImageNode; } }); };}
2. 创建强大的响应式图像组件
第二步是实现 <markdown-image>
标签对应的 Astro 组件——MarkdownImage.astro
。这个组件是所有响应式魔法发生的地方,它利用了 Astro 内置的 astro:assets
功能。
---import { Image } from "astro:assets";
interface Props { src: string; alt: string; }const { src, alt } = Astro.props;const isRemote = src.startsWith("http");---
<figure class="flex flex-col items-center"> { isRemote ? ( <img {src} {alt} class="rounded-lg" /> ) : ( <Image src={/* ...动态导入本地图片的逻辑... */} {alt} class="rounded-lg" widths={[400, 800, 1200]} sizes="(max-width: 800px) 100vw, 800px" format="webp" /> ) } {alt && <figcaption class="mt-2 text-center text-sm">{alt}</figcaption>}</figure>
这个组件的核心逻辑是:
- 区分来源:判断图片是远程链接还是本地文件。
- 处理本地图片:对于本地图片,使用 Astro 的
<Image>
组件。widths
和sizes
属性让 Astro 自动生成不同尺寸的图片,并告诉浏览器如何根据屏幕大小选择最合适的版本。format="webp"
会自动将图片转换为高效的 WebP 格式。- Astro 的
<Image>
组件还内置了懒加载 (loading="lazy"
) 和其他性能优化。
- 处理远程图片:对于远程图片,则回退到使用标准的
<img>
标签,不进行优化处理。 - 语义化包裹:最后,使用
<figure>
和<figcaption>
为图片提供正确的 HTML 语义。
结论
通过“Rehype 插件拦截替换” + “Astro Assets 组件实现优化”的组合拳,博客实现了一套全自动、高性能且对内容创作者完全透明的响应式图像解决方案。这不仅极大地提升了网站的加载速度和用户体验,也展示了 Astro 在内容处理和性能优化方面的强大灵活性。
在 Astro 中实现全自动响应式图像:结合 Rehype 与 astro:assets
https://www.497995.xyz/posts/responsive-images/