Astro 7.0

Hacker News Top 工具

摘要

Astro 7.0 是一个主要版本,专注于速度提升,具备 Rust 编译器、基于 Rust 的 Markdown/MDX 处理、基于队列的渲染引擎、Vite 8 及 Rolldown 打包器、路由缓存以及 AI 开发增强功能。

暂无内容
查看原文
查看缓存全文

缓存时间: 2026/07/07 20:14

# Astro 7.0 来源:https://astro.build/blog/astro-7/ **Astro 7 来了!** 这个版本的全部重点就是速度。`.astro` 编译器已用 Rust 重写。Markdown 和 MDX 处理现在通过新的 Rust 驱动管道运行。渲染引擎已替换为更快的基于队列的方法。与 Vite 8 及其新的 Rolldown 打包器一起,Astro 7 的构建在我们的基准测试中快了 15-61%。最快的构建就是根本不发生的构建,所以 Astro 7 还稳定了路由缓存,并为 Netlify、Vercel 和 Cloudflare 添加了实验性 CDN 缓存提供商。Astro 7 还引入了高级路由,为你提供一个 `src/fetch.ts` 入口点,完全控制 Astro 的请求管道。对于 AI 辅助开发,Astro 现在可以检测编码代理,在后台运行开发服务器,并在代理需要机器可读反馈时输出结构化的 JSON 日志。完整版本亮点包括: - **Vite 8 (https://astro.build/blog/astro-7/#vite-8)** - **性能 (https://astro.build/blog/astro-7/#performance)** - **Rust 编译器 (https://astro.build/blog/astro-7/#rust-compiler)** - **Markdown 和 MDX 在 Rust 中 (https://astro.build/blog/astro-7/#markdown--mdx-in-rust)** - **队列渲染 (https://astro.build/blog/astro-7/#queued-rendering)** - **高级路由 (https://astro.build/blog/astro-7/#advanced-routing)** - **路由缓存 (https://astro.build/blog/astro-7/#route-caching)** - **CDN 缓存提供商 (https://astro.build/blog/astro-7/#cdn-cache-providers)** - **AI 增强 (https://astro.build/blog/astro-7/#ai-enhancements)** - **后台开发服务器 (https://astro.build/blog/astro-7/#background-dev-server)** - **JSON 日志 (https://astro.build/blog/astro-7/#json-logging)** - **社区 (https://astro.build/blog/astro-7/#community)** ## 立即升级 要将现有项目升级到 Astro 7,请使用自动化的 `@astrojs/upgrade` CLI 工具: `` # 推荐: npx @astrojs/upgrade # 手动: npm install astro@latest `` 对于新项目,只需使用: 查看升级指南 (https://docs.astro.build/en/guides/upgrade-to/v7/) 了解详细的迁移步骤。 ## Vite 8 Astro 7 升级到了 Vite 8 (https://vite.dev/blog/announcing-vite8),这是多年来最重要的 Vite 版本。标题性变化:Vite 现在搭载了 Rolldown (https://rolldown.rs/),一个基于 Rust 的打包器,同时替代了 esbuild 和 Rollup,成为一个统一的打包器。在基准测试中,Rolldown 比 Rollup 快 10-30 倍 (https://github.com/rolldown/benchmarks),同时支持相同的 Rollup 和 Vite 插件 API。对于 Astro 用户来说,这意味着更快的构建,并且大部分项目无需更改配置。Vite 8 包含一个兼容层,可以将现有的 `esbuild` 和 `rollupOptions` 配置自动转换为其 Rolldown 等效项。如果你的项目使用了自定义的 Vite 插件,大多数应该能继续工作,因为 Rolldown 支持与 Rollup 相同的插件 API。 ## 性能 Astro 7 是迄今为止最快的 Astro 版本。随着使用量的增长,越来越多的团队正在突破使用 Astro 能构建的网站类型的界限。在我们发布 Astro 6 及其庞大的内部重构之后,我们将目光投向了帮助 Astro 扩展到更大、更复杂的网站。Astro 构建的工作方式如下: 1. 将网站的页面、内容和客户端组件打包成 JavaScript。 2. 像一个小型服务器一样运行打包的代码,为每个预渲染页面创建请求,并保存生成的 HTML。 Astro 7 改进了这两个步骤,但重点放在第一步:打包网站。最大的收益来自于将构建中最慢的部分迁移到用 Rust 编写的原生代码中。生成步骤也更快,这要归功于一种新的渲染策略,可以更有效地将部分内容排队渲染。在我们的测试中,总体构建时间提高了 15–61%,有些网站**构建速度提升了一倍以上**。`.astro` 编译和 Markdown 处理在构建中占比较高的网站收益最大,因为这些正是迁移到 Rust 的部分。这些基准测试是在配备 48 GB 内存的 MacBook Pro Apple M4 Pro 上运行的: | 网站 | 之前 | 之后 | |------|------|------| | https://docs.astro.build/ (~6,313 页) | 114.54s | 73.53s | | https://astro.build/ (~308 页) | 62.70s | 24.24s | | https://biomejs.dev/ (~6,488 页) | 176.39s | 149.90s | | https://developers.cloudflare.com/ (8,431 页) | 386.89s | 261.94s | | https://tauri.app/ (7,117 页) | 86.12s | 55.33s | | https://aspire.dev/ (13,275 页) | 385.84s | 326.11s | ### Rust 编译器 我们为 `.astro` 组件格式构建了一个新的编译器,现在用 Rust 编写。该编译器是对之前基于 Go 的编译器的完全重写,大部分向后兼容,除了: - **不再进行 HTML 修正。** Go 编译器会静默地重写你的标记以使其“有效 HTML”,通过重新排序元素、自动闭合标签和移动节点,这些操作常常让用户感到意外并导致难以调试的问题。新编译器按原样处理你的标记。 - **JSX 风格的严格性。** 未闭合的标签如 `Hello` 和未终止的属性如 `HelloWorld` 现在会导致错误。以前像 `<p>Hello` 这样的写法会被纠正为 `<p>Hello</p>`,现在你必须自己闭合标签,否则构建会失败。类似地,字符串插值现在遵循 JSX 规则:`HelloWorld` 会被视为普通文本,而 `Hello{' '}World` 会在单词之间插入一个空格。 迁移到 Rust 使我们能够为支持的平台提供原生二进制文件,并为需要它的环境提供 WASM 回退。这种模式现在已成为 JavaScript 工具世界的标准,被 Rolldown 和 Lightning CSS 等项目使用。在内部,新编译器基于 oxc (https://oxc.rs/) 进行解析,并使用 Lightning CSS (https://lightningcss.dev/) 进行 CSS 作用域限定。单独来看,Rust 编译器在 https://docs.astro.build/ 上显示构建时间大约提升了 6%。这是因为 `.astro` 编译很少是瓶颈;Markdown 处理和打包通常主导构建时间。但每一点的提升都很重要,尤其是在有数千页的大型网站上,而且编译器的提升与本版本中的其他性能改进相结合。 ### Markdown 和 MDX 在 Rust 中 Astro 7 将默认的 Markdown 和 MDX 管道替换为 Sätteri (https://satteri.bruits.org/),这是一个由 Astro 核心团队成员 Erika (https://bsky.app/profile/erika.florist) 创建的 Rust 驱动处理器。将 Astro 文档和 Cloudflare 文档构建切换到 Sätteri 后,构建时间缩短了一分多钟,使得 Markdown 密集型网站成为 Astro 7 的最大赢家。直到现在,Astro 的 Markdown 管道一直运行在 unified (https://unifiedjs.com/)(remark、rehype 和一长串 JavaScript 依赖项)之上。在拥有数千页的大型网站上,这个管道通常是构建中最慢的阶段:每个文件通过 JavaScript 解析,经过一个又一个插件遍历整个 AST,然后序列化为 HTML。在 Astro 6.4 中,我们使管道可插拔 (https://astro.build/blog/astro-640/#new-markdownprocessor-api) 并发布了 Sätteri 作为可选方案。Astro 7 将其设为默认。在内部,Sätteri 使用 pulldown-cmark (https://github.com/pulldown-cmark/pulldown-cmark) 进行 CommonMark 解析,使用 Oxc (https://oxc.rs/) 进行 MDX 表达式解析,两者都是原生的 Rust。它提供平台特定的二进制文件,并带有 WASM 回退,与新的 `.astro` 编译器采用相同的方法。不过,速度不是唯一的优势。Sätteri 还原生实现了许多以前需要单独插件的 Markdown 功能: | 功能 | unified | Sätteri | |------|---------|---------| | GFM(表格、脚注、删除线、任务列表) | remark-gfm 插件 | 内置,默认开启 | | 智能标点(弯引号、长破折号) | remark-smartypants 插件 | 内置 | | 标题 ID | remark-heading-id 或类似插件 | 内置 | | 容器指令 | remark-directive 插件 | 内置 | | 数学公式 | remark-math 插件 | 内置 | | Frontmatter(YAML、TOML) | remark-frontmatter 插件 | 内置 | | 上标/下标 | remark-supersub 或类似插件 | 内置 | | 维基链接 | remark-wiki-link 插件 | 内置 | 非默认功能通过 `features` 选项启用: ```javascript import { defineConfig } from 'astro/config'; import { satteri } from '@astrojs/markdown-satteri'; export default defineConfig({ markdown: { processor: satteri({ features: { directive: true, math: true, headingAttributes: true, }, }), }, }); ``` Sätteri 也有自己的插件 API。插件声明它们关心的节点类型,并跳过其余节点,而不是每次遍历整个树。这使得添加插件的成本远低于 unified,在 unified 中每个插件都会遍历每个节点。如果你依赖 remark 或 rehype 插件,基于 unified 的管道仍可通过 `@astrojs/markdown-remark` 使用: ```javascript import { defineConfig } from 'astro/config'; import { unified } from '@astrojs/markdown-remark'; import remarkToc from 'remark-toc'; export default defineConfig({ markdown: { processor: unified({ remarkPlugins: [remarkToc], }), }, }); ``` 了解更多关于 Sätteri 的功能和插件 API,请访问 satteri.bruits.org (https://satteri.bruits.org/)。 ### 队列渲染 队列渲染在 Astro 6.0 中以实验性选项引入,现在已稳定并成为默认渲染引擎。它的速度**快了约 2.4 倍**¹ (https://astro.build/blog/astro-7/#user-content-fn-1)! ```javascript import { defineConfig } from "astro/config"; export default defineConfig({ experimental: { queuedRendering: { enabled: true, pooling: true, contentCache: 1000 } } }) ``` 以前,Astro 使用递归方法渲染页面,子节点使用相同的 `render*` 函数渲染,如下面的伪代码所示: ```javascript export function renderComponentToString(node: unknown): string { let destination = ""; destination += `<${node.name}>`; // 开始标签 // 渲染属性 for (const child of node.children) { // 这里我们递归子节点,调用 renderComponentToString destination += renderComponentToString(child); } destination += `</${node.name}>`; // 结束标签 return destination; } ``` 新引擎使用队列(或栈)和单个循环。队列按正确顺序填充子节点,循环持续渲染节点直到队列为空。以下伪代码是对实际情况的过度简化,但应该能提供清晰的画面: ```javascript export function renderComponentToString(root: unknown): string { let destination = ""; destination += `<${root.name}>`; // 开始标签 // 这是我们的队列,在渲染过程中填充并刷新 let stack = [root]; while (stack.length > 0) { const node = stack.pop(); if (Array.isArray(node)) { // 最后的节点必须首先渲染到目的地 for (let i = node.length - 1; i >= 0; i--) stack.push(node[i]); continue; } const nodeType = typeof node; if (nodeType === 'string') { destination += escapeHTML(node as string); } } destination += `</${root.name}>`; // 结束标签 return destination; } ``` 该策略的第一个实现分为两个阶段:创建一个有序的组件(节点)列表,然后循环列表并渲染组件。新的实现不再创建完整的列表,而是在循环列表的同时渲染(刷新)列表。这种最终方法比第一次迭代更快,并且与递归方法相比需要更少的内存。 ## 高级路由 Astro 最初是一个基于文件的静态站点生成器。随着时间的推移,中间件、重定向、重写、Actions、会话和 i18n 等功能赋予了 Astro 应用更多的服务器端能力,但也使得请求生命周期更难控制。如果你需要在 Actions 之前运行身份验证,只想在页面渲染时包装日志记录,或者希望先由非 Astro API 处理某些请求,你必须绕过管道而不是直接组合它。在 Astro 7 中,你现在可以通过在项目中添加 `src/fetch.ts` 文件来完全控制 Astro 的请求管道。该文件导出了由 Cloudflare Workers (https://developers.cloudflare.com/workers/runtime-apis/handlers/fetch/)、Deno (https://docs.deno.com/runtime/fundamentals/http_server/) 和 Bun (https://bun.sh/docs/api/http#bun-serve) 推广的标准 `fetch` 处理程序模式。 ```typescript import { astro, FetchState } from 'astro/fetch'; export default { fetch(request: Request) { const state = new FetchState(request); // 将 API 请求转发到后端服务 if (state.url.pathname.startsWith('/api')) { const url = new URL(state.url.pathname + state.url.search, 'https://backend-api.example.com'); return fetch(new Request(url, request)); } // 回退到 Astro 页面/端点 return astro(state); } } ``` 该 API 也与 Hono (https://hono.dev/) 兼容,允许你将 Hono 中间件引入你的 Astro 应用程序: ```typescript import { astro } from 'astro/hono'; import { Hono } from 'hono'; import { basicAuth } from 'hono/basic-auth'; const app = new Hono(); app.use(basicAuth({ username: 'admin', password: 'secret' })); app.use(astro()); export default app; ``` 对于高级用法,你可以将单个 Astro 功能作为单独的中间件组合,从而完全控制请求管道。如果你曾经使用过 Astro 中间件,并因为身份验证检查在 Astro Actions *之后*运行,或者无法在不自己包裹所有内容的情况下记录响应时间而感到沮丧,现在你可以将代码放在它需要的位置: ```typescript import { Hono } from 'hono'; import { actions, middleware, pages, i18n } from 'astro/hono'; import { auth } from './middleware/auth'; import { timing } from './middleware/timing'; const app = new Hono(); app.use(i18n()); app.use(auth()); // 身份验证在Actions之前运行,没有未经验证的调用 app.use(actions()); app.use(middleware()); app.use(timing()); // 计时只包装页面渲染 app.use(pages()); export default app; ``` 如果你不添加 `src/fetch.ts` 文件,Astro 的行为与现在完全相同。 ## 路由缓存 按需渲染响应的缓存比应有的方式更难。每个主机都以不同的方式处理,并且从未有一种标准的方法从应用程序代码中控制它。Astro 7 引入了路由缓存 (https://docs.astro.build/en/guides/caching/) 来解决这个问题。该功能首次在 Astro 6 (https://astro.build/blog/astro-6/#experimental-route-caching) 中实验性发布,现在已稳定,并添加了一个统一的、与平台无关的缓存 API:在路由中设置指令,Astro 会处理其余部分,无论你部署到哪里。你配置一次缓存提供商,然后在页面中使用 `Astro.cache`(或在 API 路由和中间件中使用 `context.cache`)根据标准的 HTTP 缓存语义来控制每次响应的缓存。Astro 自带内置的 `memoryCache()` 提供商,让你快速上手: ```javascript import { defineConfig, memoryCache } from 'astro/config'; export default defineConfig({ cache: { provider: memoryCache(), }, }); ``` ```astro --- Astro.cache.set({ maxAge: 120, // 缓存 2 分钟 swr: 60, // 后备缓存 1 分钟,同时重新验证 tags: ['products'], // 用于定向失效的标签 }); --- ``` 你还可以在配置中使用 `routeRules` 声明性地为路由组定义缓存规则,从而将缓存逻辑完全排除在路由代码之外: ```javascript export default defineConfig({ cache: { provider: memoryCache() }, routeRules: { '/blog/[...path]': { maxAge: 300, swr: 60 }, }, }); ``` 路由缓存的真正亮点在于它与实时内容集合 (https://docs.astro.build/en/guides/content-collections/#live-content-collections) 的集成。一个实时加载器可以为返回的数据附加一个缓存提示,包含用于失效的标签和用于新鲜度的最后修改时间。将该条目直接传递给 `Astro.cache.set()`,Astro 会为你读取该提示,无需手动设置头部: ```astro --- import { getLiveEntry } from 'astro:content'; const { entry } = await getLiveEntry('products', Astro.params.id); // Astro 从条目中读取加载器的缓存提示: Astro.cache.set(entry); --- ``` 缓存的响应可以通过 `cache.invalidate()` 按需清除,可以通过标签或路径。例如,你可以为你的 CMS 暴露一个 webhook 端点,当内容发生变化时调用它。这映射到每个提供商的失效 API,无需重新构建即可清除所有受影响的响应: ```typescript import type { APIRoute } from 'astro'; export const POST: APIRoute = async ({ request, cache }) => { // 实际实现会验证

相似文章

WordPress 7.0

Lobsters Hottest

WordPress 7.0 是一个重大版本,包含重新设计的导航覆盖层、通过集中式 Connectors 中心实现的人工智能集成、可视化修订、将模式作为单个块处理、性能提升、改进的可访问性以及焕然一新的管理体验。

GPT-6 Astra

Product Hunt

OpenAI发布GPT-6 Astra,这是其最强大的AI模型,适用于高级推理、软件工程和智能体工作流,具备异步工具调用和中途引导功能,并制定了分阶段推出计划。