Astro 5.10

作者
Matt Kane

🎥 这次我们直播——我们始终响应您的需求。

Astro 5.10 为所有人带来了响应式图片,以及实验性的实时内容集合、CSP 改进等更多功能!

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

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

实验性实时内容集合

Astro 5.10 引入了一项新的实验性功能:实时内容集合。这一强大的新增功能允许您在运行时而非构建时获取内容,为动态、实时内容开辟了新的可能性。

构建时内容集合非常适合变化不大的内容,或者当您的站点在内容变化时能够快速轻松地重建的场景。但对于频繁变化或需要根据用户进行个性化设置的数据怎么办?实时内容集合通过允许您在每次请求时获取最新数据来弥补这一空白。

工作原理

实时内容集合使用了一种新的加载器类型,可在运行时获取数据。与在构建过程中运行的现有加载器不同,实时加载器在用户访问您的页面时执行,确保您始终拥有最新数据。

为获得最佳性能,您应尽可能使用构建时集合。但现在您可以将实时集合用于需要最新数据,或希望根据用户输入、凭据或偏好来过滤或个性化数据的情况。

要开始使用,请在您的 Astro 配置中启用实验性实时内容集合

astro.config.mjs
export default defineConfig({
experimental: {
liveContentCollections: true,
},
});

创建 `src/live.config.ts` 文件来定义您的实时集合

src/live.config.ts
import { defineLiveCollection } from 'astro:content';
import { storeLoader } from './loaders/store';
export const products = defineLiveCollection({
type: 'live',
loader: storeLoader({
apiKey: process.env.STORE_API_KEY,
endpoint: 'https://api.mystore.com/v1',
}),
});

获取实时数据

使用新的 `getLiveCollection()` 和 `getLiveEntry()` 函数在您的组件中获取数据

src/pages/products/[slug].astro
---
import { getLiveEntry } from 'astro:content';
const { entry: product, error } = await getLiveEntry(
'products',
Astro.params.slug,
);
if (error) {
console.error('Failed to load product:', error);
return Astro.rewrite('/404');
}
---
<h1>{product.data.name}</h1>
<p>
{
Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(
product.data.price,
)
}
</p>

渲染实时内容

实时加载器可以生成渲染后的内容,就像构建时加载器一样,使得在组件中显示动态数据变得非常容易

src/pages/products/[slug].astro
---
import { getLiveEntry, render } from 'astro:content';
const { entry: product, error } = await getLiveEntry(
'products',
Astro.params.slug,
);
if (error) {
console.error('Failed to load product:', error);
return Astro.rewrite('/404');
}
const { Content } = await render(product);
---
<h1>{product.data.name}</h1>
<Content />

灵活的过滤

实时加载器支持加载器特定的查询和过滤选项,允许您将过滤逻辑推送到 API 层面,以实现更高效的数据获取。这意味着您可以请求所需的确切数据,而不是获取所有数据并在客户端进行过滤。

src/pages/products.astro
---
import { getLiveCollection } from 'astro:content';
const { entries, error } = await getLiveCollection('products', {
category: 'electronics',
priceRange: { min: 10, max: 100 },
});
---

错误处理

实时内容集合提供了明确的错误处理机制,结果对象包含数据或一个 `error` 对象。这使得运行时行为可预测,并帮助您优雅地处理故障。

类型安全

如果 Astro 不是以类型安全为核心构建的,那它就不是 Astro 了,所以其 API 是完全类型安全的,通用类型确保您的数据和查询选项正确类型化

// Custom loader with typed queries and data
const { entry, error } = await getLiveEntry('products', {
uuid: Astro.params.uuid, // Filter options are type-checked
});
// `entry` will be typed

实时内容集合是实验性功能,我们正在积极征集社区反馈。在您的项目中试用它们,并告诉我们它们对您的作用!

有关更多详细信息,包括如何构建实时加载器,请参阅实验性实时内容集合文档。请在RFC上向我们提供您的反馈。

响应式图片现已稳定

Astro 响应式图片功能现已稳定并可用于生产环境!

响应式图片会自动生成优化的 `srcset` 和 `sizes` 属性,并且可以生成所需的样式,确保您的图片在所有屏幕尺寸下都能快速加载并精美显示。告别影响您的 Core Web Vitals 分数的布局偏移和缓慢加载的图片。

开始使用响应式图片

`layout` 属性定义了您的响应式图片应如何调整大小,并确定要生成的 `srcset` 和 `sizes`。您可以将其全局设置在 Astro 配置中以默认应用于所有图片,或者在 `` 或 `` 组件中按图片单独设置。要启用此响应式行为,请配置 Astro 支持内置布局选项的默认全局响应式样式

astro.config.mjs
export default defineConfig({
image: {
responsiveStyles: true,
layout: 'constrained',
},
});

布局选项: 从 `constrained`(受限)、`fixed`(固定)或 `full-width`(全宽)布局中选择,以控制图片行为。在单个组件上设置此值将覆盖您的默认布局。例如,您可以添加 `layout` 属性来创建全宽英雄图片,同时保持其余图片受限于其容器

<Image
src="/hero.jpg"
alt="A panoramic view of the mountains"
layout="full-width"
/>

优先加载: 使用新的 `priority` 属性来优化出现在首屏的关键图片

<Image src="/hero.jpg" alt="Hero image" priority />

当您添加 `priority` 时,Astro 会自动设置 `loading="eager"`、`decoding="sync"` 和 `fetchpriority="high"`,以确保图片立即加载。请谨慎使用此功能——理想情况下,每页最多只有一张图片应具有优先加载。在使用前请确保您需要此功能!检查您的最大内容绘制(LCP)元素是否是图片,如果是,请在其上设置 `priority` 标志,以便您的访问者更快地看到它。

增强的裁剪控制: `fit` 和 `position` 属性让您可以精确控制图片的裁剪和定位方式

<Image
src="/profile.jpg"
alt="Profile photo"
fit="cover"
position="center top"
width={300}
height={300}
/>

从实验性响应式图片升级

如果您曾使用实验性响应式图片,则必须从 `astro.config.mjs` 文件中移除实验性标志,并将其 `image.experimental` 选项更新为稳定版本

astro.config.mjs
export default defineConfig({
experimental: {
responsiveImages: true,
},
image: {
responsiveStyles: true,
},
});

有关完整详细信息,请参阅更新后的图片指南

实验性内容安全策略的改进

Astro 5.9 发布了对内容安全策略 (CSP) meta 标签的实验性支持,为您的 Astro 站点带来了强大的安全功能。在 5.10 中,我们根据社区反馈进行了多项改进。最重要的是,我们现在支持生成 CSP 标头,包括用于静态页面。

按需渲染的页面现在将为 CSP 发送响应标头,而不是 meta 标签。这提高了 Chrome 浏览器中的性能,并增加了对更多指令的支持,例如 `report-uri` 和 `frame-ancestors`,这些指令在 meta 标签中不受支持。

默认情况下,预渲染页面仍将使用 meta 标签,但现在通过官方适配器也核心支持为预渲染页面生成标头。最终,这将应用于所有适配器,但目前只有 `@astrojs/netlify` 和 `@astrojs/vercel` 适配器支持此功能。要启用此功能,请确保您已更新到最新版本的适配器,并将 `experimentalStaticHeaders` 选项添加到您的适配器配置中

astro.config.mjs
import { defineConfig } from 'astro/config';
import netlify from '@astrojs/netlify';
export default defineConfig({
adapter: netlify({
experimentalStaticHeaders: true,
}),
experimental: {
csp: true,
},
});

有关更多详细信息,请参阅实验性 CSP 文档

可定制的 Cloudflare Workers 入口点

某些 Cloudflare Workers 功能,例如 Durable Objects、Cloudflare Queues 和 Cron Triggers,需要自定义入口点文件。由于 `@astrojs/cloudflare` 适配器生成用于服务站点的入口点,因此以前无法将这些功能与 Astro 一起使用。此版本增加了对自定义 `@astrojs/cloudflare` 适配器使用的入口点文件的支持,让您可以完全控制 Cloudflare Workers 的设置。

要自定义入口点,请将 `workerEntryPoint` 选项添加到您的 `astro.config.mjs` 文件中的 `@astrojs/cloudflare` 适配器配置中

astro.config.mjs
import { defineConfig } from 'astro/config';
import cloudflare from '@astrojs/cloudflare';
export default defineConfig({
adapter: cloudflare({
workerEntryPoint: {
path: 'src/worker.ts',
namedExports: ['MyDurableObject']
}
}),
});

然后,您可以在指定路径创建自定义入口点文件,该文件可以包含您的 Workers 设置所需的任何额外导入或导出。此示例配置了一个自定义入口文件,用于注册 Durable Object 和队列处理程序

src/worker.ts
import type { SSRManifest } from 'astro';
import { App } from 'astro/app';
import { handle } from '@astrojs/cloudflare/handler'
import { DurableObject } from 'cloudflare:workers';
class MyDurableObject extends DurableObject<Env> {
constructor(ctx: DurableObjectState, env: Env) {
super(ctx, env)
}
}
export function createExports(manifest: SSRManifest) {
const app = new App(manifest);
return {
default: {
async fetch(request, env, ctx) {
// Your bindings must also be defined in your `wrangler.toml`/`wrangler.jsonc` file
await env.MY_QUEUE.send("log");
// Make sure you pass the request to Astro's handler
return handle(manifest, app, request, env, ctx);
},
async queue(batch, _env) {
let messages = JSON.stringify(batch.messages);
console.log(`consumed from our queue: ${messages}`);
}
} satisfies ExportedHandler<Env>,
MyDurableObject,
}
}

有关更多详细信息,请参阅更新后的Cloudflare 适配器文档

感谢 Alexander Niebuhr 贡献了此功能,并完成了 `@astrojs/cloudflare` 适配器的大部分工作!

错误修复

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

社区

Astro 核心团队成员是

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

感谢所有其他贡献者,他们通过代码和文档的添加和改进,帮助实现了 Astro 5.9,包括

Alexander Niebuhr, Anshul Gupta, Armand Philippot, benosmac, Han Seung Min - 한승민, Junseong Park, kato takeshi, knj, liruifengv, Martin Haug, Martin Trapp, Nin3, Paul Valladares, Quinn Blenkinsop, Thomas Bonnet, and zaitovalisher