View Transitions API
Astro 内置了 View Transitions API 支持,让多页面应用(MPA)获得类似单页面应用(SPA)的平滑过渡动画。全局启用只需要在 <head> 中添加一个标签:
---
// src/layouts/DocLayout.astro
import { ViewTransitions } from 'astro:transitions'
---
<html lang="zh-CN">
<head>
<ViewTransitions />
<!-- 其他 head 内容 -->
</head>
<body>
<slot />
</body>
</html>
启用后,站内导航会触发页面过渡动画,而不是硬刷新。
自定义过渡动画
可以为特定元素指定过渡名称,实现元素级别的动画:
---
// src/pages/index.astro
import { transition } from 'astro:transitions'
---
<h1 transition:name="page-title">首页</h1>
<img
src="/hero.jpg"
transition:name="hero-image"
alt="Hero"
/>
当两个页面拥有相同 transition:name 的元素时,Astro 会自动执行 DOM 元素的平滑过渡(morph),而不是整个页面的替换。
过渡指令
Astro 提供了多个 transition:* 指令控制动画行为:
<nav transition:persist="nav-menu">
<!-- 这个元素在页面切换时保持状态,不会重新渲染 -->
</nav>
<div transition:animate="slide">
<!-- 使用预设的滑动动画 -->
</div>
可用的动画预设:fade、slide、morph、initial、none。
Islands 架构
Astro 的 Islands 架构是其核心性能优势。默认情况下,组件只在构建时渲染为静态 HTML。使用 Client Directives 可以精确控制哪些组件需要客户端 JavaScript。
Client Directives 详解
---
import InteractiveCounter from '../components/InteractiveCounter'
import HeavyChart from '../components/HeavyChart'
import LazyMap from '../components/LazyMap'
import BlogComment from '../components/BlogComment'
---
<!-- 页面加载时立即水合 -->
<InteractiveCounter client:load />
<!-- 元素进入视口时水合(懒加载) -->
<HeavyChart client:visible />
<!-- 浏览器空闲时水合(低优先级) -->
<LazyMap client:idle />
<!-- HTML 只与当前元素交互时水合 -->
<BlogComment client:only="react" />
各指令的适用场景:
| 指令 | 时机 | 适用场景 |
|---|---|---|
client:load | 页面加载立即执行 | 导航栏、搜索框、需要立即交互的元素 |
client:idle | 浏览器 requestIdleCallback | 分析图表、非关键 UI |
client:visible | 元素进入视口 | 长页面下方的评论区、图片轮播 |
client:media | 匹配媒体查询 | 响应式组件 |
client:only | 仅客户端渲染 | 依赖浏览器 API 的组件 |
组合使用示例
---
// src/pages/dashboard.astro
import Sidebar from '../components/Sidebar.astro'
import RealtimeChart from '../components/RealtimeChart'
import NotificationToast from '../components/NotificationToast'
---
<Sidebar />
<main>
<article>
<!-- 静态内容,零 JS -->
<h1>仪表盘</h1>
<p>欢迎回来!这是你的数据概览。</p>
</article>
<!-- 仅图表部分需要 JS -->
<RealtimeChart client:visible />
<!-- 轻量级交互 -->
<NotificationToast client:load />
</main>
这样设计的结果是:页面主体是纯 HTML,只有 RealtimeChart 和 NotificationToast 会加载少量 JS,页面整体性能远高于全 SPA 方案。
图片优化
Astro 内置的 Image 和 Picture 组件提供自动优化:
---
import { Image, Picture } from 'astro:assets'
import heroImage from '../assets/hero.jpg'
---
<!-- 自动生成 WebP/AVIF 格式、调整尺寸、懒加载 -->
<Image
src={heroImage}
alt="Banner 图片"
width={1200}
height={630}
format="avif"
loading="lazy"
decoding="async"
/>
<!-- 响应式图片:不同视口输出不同的分辨率 -->
<Picture
src={heroImage}
formats={['avif', 'webp', 'jpg']}
widths={[480, 768, 1200]}
sizes="(max-width: 768px) 100vw, 1200px"
alt="响应式 Banner"
/>
Image 组件的优化能力:
- 自动转换为 WebP / AVIF 等现代格式
- 生成多分辨率源文件
- 内置懒加载(
loading="lazy") - 防止布局偏移(自动注入宽高属性)
对于 public/ 目录中的外部图片,可以手动使用 getImage() 工具函数:
---
import { getImage } from 'astro:assets'
const optimized = await getImage({
src: '/external-photo.jpg',
width: 800,
quality: 80,
})
---
<img src={optimized.src} width={optimized.width} height={optimized.height} alt="" />
性能审计
使用浏览器 DevTools 的 Lighthouse 面板对站点进行性能审计。以下是 Astro 项目的常见优化目标:
核心 Web 指标
| 指标 | 含义 | Astro 的优势 |
|---|---|---|
| LCP | 最大内容绘制 | Astro 的零 JS 默认让 LCP 极低 |
| INP | 首次交互延迟 | 仅水合必要的岛屿,INP 大幅优化 |
| CLS | 累积布局偏移 | Image 组件自动设宽高,避免布局偏移 |
常见优化措施
1. 预加载关键资源
<head>
<!-- 预加载字体 -->
<link rel="preload" href="/fonts/inter-var.woff2" as="font" crossorigin />
<!-- 预连接第三方源 -->
<link rel="preconnect" href="https://fonts.googleapis.com" />
</head>
2. 压缩图片
构建时自动压缩 SVG 和图片:
// astro.config.mjs
import { defineConfig } from 'astro/config'
export default defineConfig({
image: {
service: {
// 使用内置的 Sharp 图片处理服务
entrypoint: 'astro/assets/services/sharp',
config: {
quality: 80,
},
},
},
})
3. 分析 bundle 大小
# 构建时输出组件大小分析报告
bunx astro build
查看 dist/ 目录,确认每个页面只包含必要的 JS 文件。
Sitemap 生成
使用 @astrojs/sitemap 集成自动生成 sitemap.xml:
bun add @astrojs/sitemap
在 astro.config.mjs 中配置:
import { defineConfig } from 'astro/config'
import sitemap from '@astrojs/sitemap'
export default defineConfig({
site: 'https://docs.example.com',
integrations: [
sitemap({
// 自定义过滤规则
filter: (page) =>
!page.includes('/admin') &&
!page.includes('/draft'),
// 自定义每项属性
entryLimit: 50000,
// 自定义 changefreq
changefreq: 'weekly',
priority: 0.7,
// 配置多语言替代 URL
serialize: (item) => ({
...item,
links: [
{ lang: 'zh-CN', url: `https://docs.example.com/zh${item.url}` },
{ lang: 'en', url: `https://docs.example.com/en${item.url}` },
],
}),
}),
],
})
构建后访问 https://docs.example.com/sitemap-index.xml 查看生成的站点地图。确保 site 配置正确,否则 Sitemap 的 URL 会是空的。