Astro 5.7

作者
Matt Kane
Florian Lefebvre
Emanuele Stoppa
Nate Moore

Astro 5.7 带来了一大堆好东西,包括稳定的会话(Sessions)和 SVG 组件,以及一个新的实验性字体 API。

🐣 沐浴着北半球春天的喜悦,Astro 5.7 带着满满的好东西来了

要升级现有项目,请使用自动化的 @astrojs/upgrade CLI 工具。或者,通过运行包管理器的升级命令来手动升级

# Recommended:
npx @astrojs/upgrade
# Manual:
npm install astro@latest
pnpm upgrade astro --latest
yarn upgrade astro --latest

实验性字体 API

如今,几乎每个网站都使用自定义字体。然而,要正确使用它们可能会出奇地复杂:为什么我会看到无样式文本闪烁(FOUC)?我应该添加预加载链接吗?预连接链接呢?我应该自托管字体还是依赖第三方提供商?

字体会对你的网站性能产生重大影响,影响访问者的浏览体验和重要的核心 Web 指标 (CWV)。幸运的是,Web API 最近得到了极大的改进,并且得益于开源社区的杰出贡献(例如 unifontcapsize),我们已经开始着手在 Astro 中开发一种出色的字体使用方式!

这个实验性功能允许你通过一个统一的 API 使用来自文件系统和几个内置支持的提供商(例如 Google、Fontsource、Bunny)的字体。借助合理的默认设置和包括备用字体生成在内的自动优化,保持你的网站高性能。

要启用此功能,请在 experimental.fonts 对象中配置一个或多个字体

astro.config.mjs
import { defineConfig, fontProviders } from "astro/config";
export default defineConfig({
experimental: {
fonts: [{
provider: fontProviders.google(),
name: "Roboto",
cssVariable: "--font-roboto"
}]
}
});

然后,在你的 <head> 中添加一个 <Font /> 组件和全站样式

src/components/Head.astro
---
import { Font } from 'astro:assets'
---
<Font cssVariable='--font-roboto' preload />
<style>
body {
font-family: var(--font-roboto);
}
</style>

还有更多内容等待你去发现!请前往实验性字体文档查看完整的 API、入门指南,甚至了解在我们尚不支持你偏好的字体服务时如何构建自己的自定义 AstroFontProvider

我们也期待你的反馈。请在字体 RFC 上参与此功能的持续开发,并帮助塑造它的未来。

会话 API

Astro 会话 API 现已稳定,可用于生产环境!

会话(Sessions)可让你在用户浏览网站页面时,安全地存储与特定用户相关的数据。与 cookie 不同,会话数据存储在服务器上,因此你可以存储更大量的数据,而无需担心大小限制或安全问题。它们可用于存储用户数据、购物车和表单状态等信息,并且无需任何客户端 JavaScript 即可工作

src/components/CartButton.astro
---
const cart = await Astro.session.get('cart');
export const prerender = false;
---
<a href="/checkout">🛒 {cart?.length ?? 0} items</a>

它们可以用在 Astro 组件、页面、API 端点、操作和中间件中。API 对所有这些场景都是相同的

src/actions/addToCart.ts
import { defineAction } from "astro:actions";
import { z } from "astro:schema";
export const server = {
addToCart: defineAction({
input: z.object({
product: z.string(),
}),
async handler({ product }, { session }) {
const cart = await session.get('cart');
session.set('cart', [...cart, product]);
},
}),
};

类型安全

当然,因为这是 Astro,你的会话也可以是类型安全的。定义一个接口,你将获得所有会话数据的类型检查和自动补全功能

src/env.d.ts
declare namespace App {
interface SessionData {
user: {
id: string;
name: string;
};
cart: string[];
}
}

会话 ID 默认使用 cookie 自动跟踪,但你也可以使用 session.load() 方法在没有 cookie 的情况下访问会话。这对于像 API 这样的场景很有用,你可能希望使用自定义标头或参数来跟踪会话 ID

src/pages/api/cart.ts
export async function POST({ session, request }: APIContext) {
const sessionId = request.headers.get('x-session-id');
// If there is an existing session ID, load it. Otherwise, one will be created
if (sessionId) {
await session.load(sessionId);
}
const cart = await session.get('cart');
const data = await request.json<{ item: string }>();
if (!data?.item) {
return new Response('Item is required', { status: 400 });
}
session.set('cart', [...cart, data.item]);
// Return the cart and session ID
return Response.json({ cart, sessionId: session.sessionId });
}

存储驱动

Astro 会话使用存储驱动来持久化数据,对于所有官方的 Astro 适配器,这些驱动要么是零配置,要么只需要最少的设置。或者,你可以使用任何 unstorage 驱动,它支持数十种存储后端,如 Redis 和 MongoDB。

  • Node: 零配置的文件系统驱动
  • Netlify: 零配置的 Netlify Blobs 驱动
  • Cloudflare: 只需最少配置的 Workers KV 驱动
  • Vercel: 只需最少配置的 Redis/Upstash 驱动

在任何这些平台上,如果你不想使用默认驱动,可以轻松地更换成其他驱动。

astro.config.mjs
import { defineConfig } from 'astro/config';
import netlify from '@astrojs/netlify';
export default defineConfig({
// ...
adapter: netlify(),
session: {
driver: 'redis',
options: {
url: process.env.REDIS_URL,
},
},
});

从实验性会话升级

如果你之前正在使用实验性会话 API,你应该从你的 astro.config.mjs 文件中移除实验性标志

astro.config.mjs
import { defineConfig } from 'astro/config';
export default defineConfig({
// ...
experimental: {
session: false,
},
});

查看会话指南以了解更多关于如何在你的 Astro 项目中使用它们的信息。

SVG 组件

Astro 现在支持将本地 SVG 文件作为组件使用!以前,将 SVG 直接内联到 HTML 中需要额外的步骤,例如手动将 SVG 转换为 Astro 组件或安装第三方集成。现在,Astro 支持将任何 .svg 文件的默认导入像使用任何其他 .astro 组件一样使用。SVG 组件会自动将一个 <svg> 标签直接内联到你的 HTML 中。

你可以传递诸如 widthheightfillstroke 以及原生 <svg> 元素接受的任何其他属性。

src/components/MyAstroComponent.astro
---
import Logo from './path/to/svg/file.svg';
---
<Logo width={64} height={64} fill="currentColor" />

查看SVG 组件文档以获取更多详细信息。

特别感谢 Michael Stramel 在此功能上所做的工作!

从实验性 SVG 升级

如果你之前正在使用实验性 SVG API,你必须从你的 astro.config.mjs 文件中移除实验性标志。

astro.config.mjs
import { defineConfig } from 'astro/config';
export default defineConfig({
// ...
experimental: {
svg: true,
},
});

请注意,Astro 5.6 对此标志引入了一些破坏性更改。请确保你的代码已更新到此 API 的最新稳定版本。

配置导入

新的虚拟模块 astro:config 现已稳定!

该虚拟模块允许你导入 Astro 配置的一个子集,并兼顾类型安全。暴露了两个子路径用于对你的配置进行受控访问

  • astro:config/client:暴露可以安全地暴露给客户端的配置信息。
  • astro:config/server:暴露可以安全地暴露给服务器的额外信息,例如文件/目录路径。

例如,你现在可以构建自己的路径实用工具,而无需依赖集成。在你的配置中设置的 basetrailingSlash 等属性可以被导入并在 .js 文件中使用

astro.config.mjs
export default defineConfig({
base: "store/",
trailingSlash: "always"
});
src/utils.js
import { trailingSlash, base } from 'astro:config/client';
// This method adds a forward slash to paths, and prepends the `base`
function addForwardSlashAndBase(path) {
let finalPath;
if (trailingSlash === 'always') {
finalPath = path.endsWith('/') ? path : path + '/';
} else {
finalPath = path;
}
if (base !== "/") {
return base + finalPath
}
return finalPath
}

在你的整个项目中使用这个依赖于你配置设置的路径实用工具,例如,为了更好地控制页面链接

src/pages/index.astro
---
import { addForwardSlashAndBase } from "@src/utils.js";
const cartUrl = addForwardSlashAndBase("cart"); // it will return "store/cart/"
---
<a href={cartUrl}>Cart</a>

我们`配置`(确信)你会喜欢这个访问你的设置的新功能,Astro 标志性的类型安全会帮助你正确使用它!

错误修复

一如既往,自 5.6 版本发布以来,我们一直在努力修复问题。请参阅更新日志以了解所有详细信息。

社区

Astro 核心团队成员是

Ben Holmes , Caleb Jasik , Chris Swithinbank , Emanuele Stoppa , Erika , Florian Lefebvre , Fuzzy , HiDeoo , Luiz Ferraz , Matt Kane , Matthew Phillips , Nate Moore , Reuben Tier , Sarah Rainsberger , 以及 Yan Thomas

感谢所有其他帮助 Astro 5.7 成为可能的贡献者,包括: Roberto MolinaJunseong ParkryuMartin TrappMichael StramelArmand PhilippotNin3viniciusdelizJuan DiazMarcos Corrochano ArroyoPaul ValladaresBugoliruifengvThomas BonnetMing-jun LuCHEZomoyxemily-shenAriel KMaciek PalmowskiMatthew JusticeAdam Matthiesen,以及 Louis Escher

我们期待看到你用 Astro 5.7 构建的作品!如果你有任何问题、评论,或者只是想打个招呼,欢迎来到 Astro Discord