升级到 Astro v5
本指南将帮助你从 Astro v4 迁移到 Astro v5。
需要先将旧项目升级到 v4?请参阅我们的旧版迁移指南。
需要查看 v4 文档?请访问旧版文档网站(未维护的 v4.16 快照)。
升级 Astro
标题为“升级 Astro”的部分使用你的包管理器将项目的 Astro 版本更新到最新版本
# Upgrade Astro and official integrations togethernpx @astrojs/upgrade
# Upgrade Astro and official integrations togetherpnpm dlx @astrojs/upgrade
# Upgrade Astro and official integrations togetheryarn dlx @astrojs/upgrade
如果需要,你还可以手动升级你的 Astro 集成,并且你可能还需要升级项目中的其他依赖项。
升级 Astro 后,你可能根本不需要对项目进行任何更改!
但是,如果你发现错误或意外行为,请查看下面的内容,了解哪些更改可能需要在你的项目中进行更新。
Astro v5.0 包含潜在的破坏性变更,以及一些功能的移除和弃用。
如果你的项目在升级到 v5.0 后无法按预期工作,请查看本指南,以获取所有破坏性变更的概述以及如何更新代码库的说明。
有关完整的发布说明,请参阅 Astro 更新日志。
依赖项升级
标题为“依赖项升级”的部分Astro 依赖项的任何主要升级都可能导致你的项目出现破坏性变更。
Vite 6.0
标题为“Vite 6.0”的部分Astro v5.0 升级到 Vite v6.0 作为开发服务器和生产打包器。
我应该怎么做?
标题为“我应该怎么做?”的部分如果你正在使用 Vite 特定的插件、配置或 API,请查看 Vite 迁移指南 以了解其破坏性变更,并根据需要升级你的项目。
@astrojs/mdx
标题为“@astrojs/mdx”的部分在 Astro v4.x 中,Astro 为 @astrojs/mdx
集成执行内部 JSX 处理。
Astro v5.0 将处理和渲染 JSX 和 MDX 的责任直接移交给了 @astrojs/mdx
包。这意味着 Astro 5.0 不再与旧版本的 MDX 集成兼容。
我应该怎么做?
标题为“我应该怎么做?”的部分如果你的项目包含 .mdx
文件,你必须将 @astrojs/mdx
升级到最新版本 (v4.0.0),以便你的 JSX 可以被集成正确处理。
如果你正在使用带有实验性 Astro 容器 API 的 MDX 服务器渲染器,你必须更新导入以反映新的位置
import mdxRenderer from "astro/jsx/server.js";import mdxRenderer from "@astrojs/mdx/server.js";
以下功能现在被视为遗留功能。它们应该可以正常工作,但不再推荐使用,并处于维护模式。它们将不会有未来的改进,文档也不会更新。这些功能最终将被弃用,然后完全移除。
遗留:v2.0 内容集合 API
标题为“遗留:v2.0 内容集合 API”的部分在 Astro 4.x 中,内容集合是使用在 Astro v2.0 中首次引入的内容集合 API 来定义、查询和渲染的。所有集合条目都是保留的 src/content/
文件夹中的本地文件。此外,Astro 的排除构建单个页面的文件名约定也内置于内容集合 API 中。
Astro 5.0 引入了使用内容层 API 的新版本内容集合,带来了多项性能改进和新增功能。虽然旧的(遗留的)和新的(内容层 API)集合可以在此版本中并存,但对现有的遗留集合存在潜在的破坏性变更。
此版本还移除了使用下划线(_
)作为集合条目文件名前缀以防止构建路由的选项。
我应该怎么做?
标题为“我应该怎么做?”的部分我们建议你尽快将任何现有集合转换为新的内容层 API,并使用内容层 API 创建任何新的集合。
如果你无法转换你的集合,请查阅遗留集合的破坏性变更,以查看你现有的集合是否受到影响并需要更新。
如果你目前无法对集合进行任何更改,你可以启用 legacy.collections
标志,这将允许你在遗留标志不再被支持之前保持集合的当前状态。
更新现有集合
标题为“更新现有集合”的部分请参阅以下说明,将现有的内容集合(type: 'content'
或 type: 'data'
)更新为使用内容层 API。
更新集合的分步说明
-
移动内容配置文件。此文件不再位于
src/content/
文件夹内。此文件现在应该存在于src/content.config.ts
。 -
编辑集合定义。你更新后的集合需要一个
loader
,它同时指示你的集合位置的文件夹(base
)和一个定义要匹配的集合条目文件名和扩展名的pattern
。(你可能需要相应地更新下面的示例。你可以使用 globster.xyz 来检查你的 glob 模式。)选择集合type
的选项已不再可用。src/content.config.ts import { defineCollection, z } from 'astro:content';import { glob } from 'astro/loaders';const blog = defineCollection({// For content layer you no longer define a `type`type: 'content',loader: glob({ pattern: '**/[^_]*.{md,mdx}', base: "./src/data/blog" }),schema: z.object({title: z.string(),description: z.string(),pubDate: z.coerce.date(),updatedDate: z.coerce.date().optional(),}),}); -
将引用从
slug
更改为id
。内容层集合没有保留的slug
字段。相反,所有更新的集合都将有一个id
src/pages/[slug].astro ---export async function getStaticPaths() {const posts = await getCollection('blog');return posts.map((post) => ({params: { slug: post.slug },params: { slug: post.id },props: post,}));}---你还可以更新动态路由文件名,以匹配已更改的
getStaticPaths()
参数的值。 -
切换到新的
render()
函数。条目不再有render()
方法,因为它们现在是可序列化的普通对象。相反,从astro:content
导入render()
函数。src/pages/index.astro ---import { getEntry, render } from 'astro:content';const post = await getEntry('blog', params.slug);const { Content, headings } = await post.render();const { Content, headings } = await render(post);---<Content />
对遗留 content
和 data
集合的破坏性变更
标题为“对遗留 content 和 data 集合的破坏性变更”的部分默认情况下,使用旧 type
属性(content
或 data
)且未定义 loader
的集合,现在在底层使用内容层 API 的内置 glob()
加载器实现,并带有额外的向后兼容性处理。
此外,存在临时的向后兼容性,以将内容配置文件保留在其原始位置 src/content/config.ts
。
这种向后兼容性实现能够模拟遗留集合的大部分功能,并允许许多遗留集合在不更新代码的情况下继续工作。然而,存在一些差异和限制,可能会对现有集合造成破坏性变更
- 在 Astro 的先前版本中,即使没有在
src/content/config.ts
中定义,也会为src/content/
中的所有文件夹生成集合。此行为现已弃用,集合应始终在src/content.config.ts
中定义。对于现有集合,这些可以是空的声明(例如const blog = defineCollection({})
),Astro 将以与新加载行为兼容的方式为你隐式定义遗留集合。 - Markdown 集合条目不支持特殊的
layout
字段。此属性仅适用于位于src/pages/
中的独立页面文件,不太可能出现在你的集合条目中。但是,如果你正在使用此属性,现在必须创建包含页面样式的动态路由。 - 生成集合的排序顺序是不确定的,并且依赖于平台。这意味着如果你调用
getCollection()
,返回条目的顺序可能与以前不同。如果你需要特定的顺序,你必须自己对集合条目进行排序。 - 不支持
image().refine()
。如果你需要验证图像的属性,你需要在页面或组件的运行时执行此操作。 getEntry(collection, key)
的key
参数被类型化为string
,而不是为每个条目都有类型。- 以前,当使用静态字符串作为键调用
getEntry(collection, key)
时,返回类型是不可空的。现在该类型包括undefined
,因此在使用结果之前,你必须检查条目是否已定义,否则将出现类型错误。
启用 legacy.collections
标志
标题为“启用 legacy.collections 标志”的部分如果你尚未准备好更新现有集合,可以启用 legacy.collections
标志,你现有的集合将继续像以前一样工作。
已弃用
标题为“已弃用”的部分以下已弃用的功能不再受支持,也不再记录在文档中。请相应地更新你的项目。
一些已弃用的功能可能会在完全移除之前暂时继续工作。其他功能可能会悄无声息地不起作用,或者抛出一个错误,提示你更新代码。
已弃用:Astro.glob()
标题为“已弃用:Astro.glob()”的部分在 Astro v4.x 中,你可以在 .astro
组件中使用 Astro.glob()
来查询项目中的多个文件。这有一些限制(例如使用位置、性能等),而使用内容集合 API 的查询函数或 Vite 自己的 import.meta.glob()
通常提供更多的功能和灵活性。
Astro 5.0 弃用了 Astro.glob()
,推荐使用 getCollection()
查询你的集合,以及使用 import.meta.glob()
查询项目中的其他源文件。
我应该怎么做?
标题为“我应该怎么做?”的部分将所有 Astro.glob()
的使用替换为 import.meta.glob()
。请注意,import.meta.glob()
不再返回 Promise
,因此你可能需要相应地更新代码。你的 glob 模式应该不需要任何更新。
---const posts = await Astro.glob('./posts/*.md');const posts = Object.values(import.meta.glob('./posts/*.md', { eager: true }));---
{posts.map((post) => <li><a href={post.url}>{post.frontmatter.title}</a></li>)}
在适当的情况下,考虑使用内容集合来组织你的内容,它有自己更新、性能更好的查询函数。
你可能还希望考虑使用来自 NPM 的 glob 包,例如 fast-glob
。
import.meta.glob
导入文件的信息。
已弃用:functionPerRoute
(适配器 API)
标题为“已弃用:functionPerRoute (适配器 API)”的部分在 Astro v4.x 中,你可以选择为项目中定义的每个路由创建一个单独的文件,在构建文件夹中镜像你的 src/pages/
目录。默认情况下,Astro 会生成一个 entry.mjs
文件,该文件负责在每个请求上输出渲染的页面。
Astro v5.0 移除了选择退出默认行为的选项。此行为现在是标准的,且不可配置。
从你的 adapterFeatures
配置中移除 functionPerRoute
属性。它已不再可用。
export default function createIntegration() { return { name: '@matthewp/my-adapter', hooks: { 'astro:config:done': ({ setAdapter }) => { setAdapter({ name: '@matthewp/my-adapter', serverEntrypoint: '@matthewp/my-adapter/server.js', adapterFeatures: { functionPerRoute: true } }); }, }, };}
已弃用:astro:build:done
钩子中的 routes
(集成 API)
标题为“已弃用:astro:build:done 钩子中的 routes (集成 API)”的部分在 Astro v4.x 中,集成从 astro:build:done
钩子访问路由。
Astro v5.0 弃用了传递给此钩子的 routes
数组。取而代之的是,它公开了一个新的 astro:routes:resolved
钩子,该钩子在 astro:config:done
之前运行,并且在开发中每当路由发生变化时都会运行。它具有已弃用的 routes
列表的所有相同属性,除了 distURL
,它只在构建期间可用。
我应该怎么做?
标题为“我应该怎么做?”的部分移除传递给 astro:build:done
的任何 routes
实例,并将其替换为新的 astro:routes:resolved
钩子。在新公开的 assets
map 上访问 distURL
const integration = () => { let routes return { name: 'my-integration', hooks: { 'astro:routes:resolved': (params) => { routes = params.routes }, 'astro:build:done': ({ routes assets }) => { for (const route of routes) { const distURL = assets.get(route.pattern) if (distURL) { Object.assign(route, { distURL }) } } console.log(routes) } } }}
astro:routes:resolved
钩子的信息。
已移除
标题为“已移除”的部分以下功能现已从代码库中完全移除,不能再使用。其中一些功能可能在弃用后仍在你的项目中继续工作。其他功能可能已经悄无声息地不起作用。
现在包含这些已移除功能的项目将无法构建,并且将不再有任何支持文档提示你移除这些功能。
已移除:Lit 集成
标题为“已移除:Lit 集成”的部分在 Astro v4.x 中,Lit 是通过 @astrojs/lit
包由核心维护的框架库。
Astro v5.0 移除了该集成,它将不会收到与 5.x及以上版本的兼容性更新。
我应该怎么做?
标题为“我应该怎么做?”的部分你可以通过添加客户端脚本标签继续使用 Lit 作为客户端组件。例如
<script> import "../components/MyTabs";</script>
<my-tabs title="These are my tabs">...</my-tabs>
如果你有兴趣自己维护 Lit 集成,你可能希望使用@astrojs/lit
的最后一个发布版本作为起点,并升级相关包。
已移除:hybrid
渲染模式
标题为“已移除:混合渲染模式”的部分在 Astro v4.x 中,Astro 提供了三种 output
渲染模式:'static'
、'hybrid'
和 'server'
Astro v5.0 将 output: 'hybrid'
和 output: 'static'
配置合并为一个单一的配置(现在称为 'static'
),其工作方式与之前的混合选项相同。
在 Astro 配置中不再需要指定 output: 'hybrid'
来使用服务器渲染的页面。新的 output: 'static'
已包含此功能。
Astro 现在将自动允许你在静态站点中选择退出预渲染,而无需更改输出配置。任何页面路由或端点都可以包含 export const prerender = false
以按需进行服务器渲染,而你网站的其余部分则静态生成。
我应该怎么做?
标题为“我应该怎么做?”的部分如果你的项目使用混合渲染,你现在必须从 Astro 配置中移除 output: 'hybrid'
选项,因为它不再存在。但是,你的项目不需要其他更改,并且应该没有破坏性变更。以前的 'hybrid'
行为现在是默认行为,新名称为 'static'
。
import { defineConfig } from "astro/config";
export default defineConfig({ output: 'hybrid',});
如果你之前使用 output: 'static'
(默认)选项,你可以像以前一样继续使用它。默认情况下,你所有的页面都将继续被预渲染,你将拥有一个完全静态的网站。你的项目应该没有破坏性变更。
无论你的项目使用哪种 output
模式,部署带有任何服务器渲染页面的 Astro 项目仍然需要一个适配器。不包含适配器将在开发中导致警告,在构建时导致错误。
已移除:对路由中动态 prerender
值的支持
标题为“已移除:对路由中动态 prerender 值的支持”的部分在 Astro 4.x 中,环境变量可用于动态设置路由中 prerender
导出的值,例如 export const prerender = import.meta.env.SOME_VAR
。
Astro v5.0 移除了对 prerender
导出中动态值的支持。仅支持静态值 true
和 false
。
我应该怎么做?
标题为“我应该怎么做?”的部分-
移除你路由中的任何动态
prerender
导出src/pages/blog/[slug].astro ---export const prerender = import.meta.env.SOME_VAR;--- -
在你的
astro.config.mjs
文件中使用 Astro 集成,在"astro:route:setup"
钩子中设置需要动态的prerender
值astro.config.mjs import { defineConfig } from 'astro/config';import { loadEnv } from 'vite';export default defineConfig({integrations: [{name: 'set-prerender',hooks: {'astro:route:setup': ({ route }) => {// Load environment variables from .env files (if needed)const { PRERENDER } = loadEnv(process.env.NODE_ENV, process.cwd(), '');// Find routes matching the expected filename.if (route.component.endsWith('/blog/[slug].astro')) {// Set the prerender value on routes as needed.route.prerender = PRERENDER;}},},}],});
已移除:Squoosh 图像服务
标题为“已移除:Squoosh 图像服务”的部分在 Astro 4.x 中,你可以配置 image.service: squooshImageService()
以使用 Squoosh 而不是 Sharp 来转换你的图像。但是,底层库 libsquoosh
已不再维护,并且存在内存和性能问题。
Astro 5.0 完全移除了 Squoosh 图像优化服务。
我应该怎么做?
标题为“我应该怎么做?”的部分要切换到内置的 Sharp 图像服务,请从你的 Astro 配置中移除 squooshImageService
导入。默认情况下,你将使用 Sharp 处理 astro:assets
。
import { squooshImageService } from "astro/config";import { defineConfig } from "astro/config";
export default defineConfig({ image: { service: squooshImageService() }});
如果你使用的是像 pnpm
这样的严格包管理器,你可能需要手动安装 sharp
包才能使用 Sharp 图像服务,即使它默认内置于 Astro 中。
如果你的适配器不支持 Astro 内置的 Sharp 图像优化,你可以配置一个空操作图像服务,以允许你使用 <Image />
和 <Picture />
组件。
或者,如果你无法使用 Sharp 图像服务,你可能希望考虑一个社区维护的 Squoosh 图像服务。
对于适配器
标题为“对于适配器”的部分如果你的适配器之前指定了其与 Squoosh 的兼容性状态,你现在应该从适配器配置中移除此信息。
supportedAstroFeatures: { assets: { isSquooshCompatible: true }}
已移除:一些面向公众的类型
标题为“已移除:一些面向公众的类型”的部分在 Astro v4.x 中,@types/astro.ts
向用户公开了所有类型,无论它们是否仍在使用中或仅供内部使用。
Astro v5.0 重构了此文件,以移除过时和内部的类型。这次重构为你的编辑器带来了改进(例如,更快的自动补全、更低的内存使用和更相关的补全选项)。但是,此重构可能会在一些依赖于不再对公众可用的类型的项目中导致错误。
我应该怎么做?
标题为“我应该怎么做?”的部分移除任何现在在你的项目中导致错误的类型,因为你已无法访问它们。这些主要是以前被弃用和移除的 API,但也可能包括现在是内部的类型。
实验性标志
标题为“实验性标志”的部分以下实验性标志已在 Astro v5.0 中移除,这些功能现已可用
env
serverIslands
此外,以下实验性标志已被移除,并且现在是 Astro v5.0 中的默认或推荐行为。
directRenderScript
(有关对默认<script>
行为的破坏性变更,请参见下文。)globalRoutePriority
(有关对默认路由优先级顺序的破坏性变更,请参见下文。)contentLayer
(有关将现有内容集合升级到新的、首选的内容层 API 的指导,请参见下文。)
以下实验性标志已被移除,并且其相应功能不属于 Astro v5.0 的一部分。
contentCollectionsCache
如果你之前正在使用这些实验性标志,请移除它们,并将你的 env
配置移动到 Astro 配置的根目录
import { defineConfig } from 'astro/config';
export default defineConfig({ experimental: { directRenderScript: true, globalRoutePriority: true, contentLayer: true, serverIslands: true, contentCollectionsCache: true, env: { schema: {...} } }, env: { schema: {...} }})
这些功能在 Astro v5.0 中都默认可用。
已更改的默认值
标题为“已更改的默认值”的部分Astro v5.0 中一些默认行为已更改,你的项目代码可能需要更新以适应这些更改。
在大多数情况下,唯一需要的操作是审查你现有项目的部署,并确保其继续按预期运行,必要时对代码进行更新。在某些情况下,可能有一个配置设置允许你继续使用以前的默认行为。
默认启用 CSRF 保护
标题为“默认启用 CSRF 保护”的部分在 Astro v4.x 中,security.checkOrigin
的默认值为 false
。以前,你必须明确将此值设置为 true
才能启用跨站请求伪造(CSRF)保护。
Astro v5.0 将此选项的默认值更改为 true
,并将在按需渲染的页面中自动检查每个请求发送的 “origin” 标头是否与 URL 匹配。
我应该怎么做?
标题为“我应该怎么做?”的部分如果你之前配置了 security.checkOrigin: true
,你不再需要在 Astro 配置中保留这一行。这现在是默认设置。
要禁用此行为,你必须明确设置 security.checkOrigin: false
。
export default defineConfig({ output: "server", security: { checkOrigin: false }})
注入路由和重定向的路由优先级顺序
标题为“注入路由和重定向的路由优先级顺序”的部分在 Astro v4.x 中,experimental.globalRoutePriority
是一个可选标志,可确保注入的路由、基于文件的路由和重定向都使用所有路由的路由优先级顺序规则进行优先级排序。这通过不自动优先处理某些类型的路由并标准化路由优先级顺序,从而更好地控制项目中的路由。
Astro v5.0 移除了此实验性标志,并将其作为 Astro 中新的默认行为:重定向和注入的路由现在与基于文件的项目路由具有同等优先级。
请注意,这已经是 Starlight 中的默认行为,不应影响已更新的 Starlight 项目。
我应该怎么做?
标题为“我应该怎么做?”的部分如果你的项目包含注入的路由或重定向,请检查你的路由是否按预期构建页面 URL。下面显示了新的预期行为示例。
在一个包含以下路由的项目中
- 基于文件的路由:
/blog/post/[pid]
- 基于文件的路由:
/[page]
- 注入的路由:
/blog/[...slug]
- 重定向:
/blog/tags/[tag] -> /[tag]
- 重定向:
/posts -> /blog
将构建以下 URL(而不是遵循 Astro v4.x 的路由优先级顺序)
/blog/tags/astro
由重定向到/tags/[tag]
构建(而不是由注入的路由/blog/[...slug]
构建)/blog/post/0
由基于文件的路由/blog/post/[pid]
构建(而不是由注入的路由/blog/[...slug]
构建)/posts
由重定向到/blog
构建(而不是由基于文件的路由/[page]
构建)
如果发生路由冲突,即两个具有相同路由优先级的路由尝试构建相同的 URL,Astro 将记录一条警告,指出冲突的路由。
<script>
标签按声明直接渲染
标题为“<script> 标签按声明直接渲染”的部分在 Astro v4.x 中,experimental.directRenderScript
是一个可选标志,用于直接渲染在 .astro
文件中声明的 <scripts>
(包括 TypeScript、导入 node_modules
和脚本去重等现有功能)。此策略可防止脚本在未使用它们的地方执行。此外,条件渲染的脚本以前是隐式内联的,就像自动为它们添加了 is:inline
指令一样。
Astro 5.0 移除了此实验性标志,并将其作为 Astro 中新的默认行为:脚本不再被提升到 <head>
,页面上的多个脚本不再被打包在一起,并且 <script>
标签可能会干扰 CSS 样式。此外,条件渲染的脚本不再隐式内联。
我应该怎么做?
标题为“我应该怎么做?”的部分请检查你的 <script>
标签,并确保它们的行为符合预期。
如果你之前有条件渲染的 <script>
标签,你需要添加一个 is:inline
属性以保持与以前相同的行为
---type Props = { showAlert: boolean}
const { showAlert } = Astro.props;---{ showAlert && <script is:inline>alert("Some very important code!!")</script>}
script
标签的信息。
破坏性变更
标题为“破坏性变更”的部分以下更改在 Astro v5.0 中被视为破坏性变更。破坏性变更可能提供也可能不提供临时的向后兼容性。如果你正在使用这些功能,你可能需要按照每个条目中的建议更新你的代码。
已重命名:<ViewTransitions />
组件
标题为“已重命名:<ViewTransitions /> 组件”的部分在 Astro 4.x 中,Astro 的视图过渡 API 包含一个 <ViewTransitions />
路由器组件,以启用客户端路由、页面过渡等功能。
Astro 5.0 将此组件重命名为 <ClientRouter />
,以阐明该组件在 API 中的作用。这使得从 Astro 的 <ClientRouter />
路由组件获得的功能与原生的基于 CSS 的 MPA 路由器略有不同这一点更加清晰。
功能没有改变。这个组件只是改了名字。
我应该怎么做?
标题为“我应该怎么做?”的部分将所有 ViewTransitions
的导入和组件替换为 ClientRouter
import { ViewTransitions } from 'astro:transitions';import { ClientRouter } from 'astro:transitions';
<html> <head> ... <ViewTransitions /> <ClientRouter /> </head></html>
已更改:TypeScript 配置
标题为“已更改:TypeScript 配置”的部分在 Astro v4.x 中,Astro 依赖 src/env.d.ts
文件进行类型推断和为依赖于生成类型的功能定义模块。
Astro 5.0 转而使用 .astro/types.d.ts
文件进行类型推断,并现在推荐在 tsconfig.json
中设置 include
和 exclude
,以从 Astro 类型中受益并避免检查已构建的文件。
运行 astro sync
不再创建或更新 src/env.d.ts
,因为它对于类型检查标准的 Astro 项目不是必需的。
我应该怎么做?
标题为“我应该怎么做?”的部分要将你的项目更新为 Astro 推荐的 TypeScript 设置,请将以下 include
和 exclude
属性添加到你现有的 tsconfig.json
中
{ "extends": "astro/tsconfigs/base", "include": [".astro/types.d.ts", "**/*"], "exclude": ["dist"]}
请注意,只有在你添加了自定义配置,或者你没有使用 tsconfig.json
文件时,才需要 src/env.d.ts
。
已更改:通过 HTML 表单提交的 Action 不再使用 cookie 重定向
标题为“已更改:通过 HTML 表单提交的 Action 不再使用 cookie 重定向”的部分在 Astro 4.x 中,从 HTML 表单调用的 action 会触发一个重定向,并通过 cookie 转发结果。这对于大型表单错误和超过 4 KB cookie 存储限制的返回值造成了问题。
Astro 5.0 现在将 action 的结果呈现为 POST 结果,而没有任何转发。当用户尝试刷新页面时,这将引入一个“确认表单重新提交?”对话框,但它不再对 action 返回值施加 4 KB 的限制。
我应该怎么做?
标题为“我应该怎么做?”的部分你应该更新依赖重定向的 action 结果处理,并可选择使用中间件来处理“确认表单重新提交?”对话框。
在出错时重定向到上一个路由
标题为“在出错时重定向到上一个路由”的部分如果你的 HTML 表单 action 指向一个不同的路由(即 action={"/success-page" + actions.name}
),Astro 将不再在出错时重定向到上一个路由。你可以使用 Astro 组件中的重定向来手动实现此行为。此示例在成功时重定向到一个新路由,否则在当前页面处理错误
---import { actions } from 'astro:actions';
const result = Astro.getActionResult(actions.newsletter);if (!result?.error) { // Embed relevant result data in the URL if needed // example: redirect(`/confirmation?email=${result.data.email}`); return redirect('/confirmation');}---
<form method="POST" action={'/confirmation' + actions.newsletter}> <label>E-mail <input required type="email" name="email" /></label> <button>Sign up</button></form>
(可选)移除刷新时的确认对话框
标题为“(可选)移除刷新时的确认对话框”的部分要处理刷新时的“确认表单重新提交?”对话框,或跨会话保留 action 结果,你现在可以通过中间件自定义 action 结果处理。
我们建议使用会话存储提供程序,如我们的 Netlify Blob 示例中所述。但是,如果你更喜欢 4.X 中的 cookie 转发行为并接受 4 KB 的大小限制,你可以实现如此示例代码段中所示的模式
import { defineMiddleware } from 'astro:middleware';import { getActionContext } from 'astro:actions';
export const onRequest = defineMiddleware(async (context, next) => { // Skip requests for prerendered pages if (context.isPrerendered) return next();
const { action, setActionResult, serializeActionResult } = getActionContext(context);
// If an action result was forwarded as a cookie, set the result // to be accessible from `Astro.getActionResult()` const payload = context.cookies.get('ACTION_PAYLOAD'); if (payload) { const { actionName, actionResult } = payload.json(); setActionResult(actionName, actionResult); context.cookies.delete('ACTION_PAYLOAD'); return next(); }
// If an action was called from an HTML form action, // call the action handler and redirect with the result as a cookie. if (action?.calledFrom === 'form') { const actionResult = await action.handler();
context.cookies.set('ACTION_PAYLOAD', { actionName: action.name, actionResult: serializeActionResult(actionResult), });
if (actionResult.error) { // Redirect back to the previous page on error const referer = context.request.headers.get('Referer'); if (!referer) { throw new Error('Internal: Referer unexpectedly missing from Action POST request.'); } return context.redirect(referer); } // Redirect to the destination page on success return context.redirect(context.originPathname); }
return next();})
已更改:compiledContent()
现在是一个异步函数
标题为“已更改:compiledContent() 现在是一个异步函数”的部分在 Astro 4.x 中,Markdown 模块中包含了顶层 await。这导致了自定义图像服务和 Markdown 内部图像的一些问题,导致 Node 突然退出且没有错误消息。
Astro 5.0 将 Markdown 导入上的 compiledContent()
属性设为异步函数,需要使用 await
来解析内容。
我应该怎么做?
标题为“我应该怎么做?”的部分更新你的代码,在调用 compiledContent()
时使用 await
。
---import * as myPost from "../blog/post.md";
const content = myPost.compiledContent();const content = await myPost.compiledContent();---
<Fragment set:html={content} />
compiledContent()
函数以返回编译后的 Markdown 的信息。
变更:astro:content
不能再在客户端上使用
标题为“变更:astro:content 不能再在客户端上使用”的部分在 Astro 4.x 中,可以在客户端上访问 astro:content
模块。
Astro 5.0 移除了这种访问方式,因为它从未被有意地暴露给客户端使用。以这种方式使用 astro:content
存在限制,并且会增大客户端包的体积。
我应该怎么做?
标题为“我应该怎么做?”的部分如果你当前正在客户端使用 astro:content
,请改为通过 props 将所需数据传递给你的客户端组件。
---import { getCollection } from 'astro:content';import ClientComponent from '../components/ClientComponent';
const posts = await getCollection('blog');const postsData = posts.map(post => post.data);---
<ClientComponent posts={postsData} />
astro:content
API 的信息。
重命名:Shiki css-variables
主题颜色令牌名称
标题为“重命名:Shiki css-variables 主题颜色令牌名称”的部分在 Astro v4.x 中,Shiki css-variables
主题分别使用 --astro-code-color-text
和 --astro-code-color-background
令牌来设置代码块的前景色和背景色。
Astro v5.0 将它们分别重命名为 --astro-code-foreground
和 --astro-code-background
,以更好地与 Shiki v1 的默认值保持一致。
我应该怎么做?
标题为“我应该怎么做?”的部分你可以在你的项目中执行全局查找和替换,以迁移到新的令牌名称。
:root { --astro-code-color-text: #000; --astro-code-color-background: #fff; --astro-code-foreground: #000; --astro-code-background: #fff;}
已更改:用于高亮代码块的内部 Shiki rehype 插件
标题为“变更:用于高亮代码块的内部 Shiki rehype 插件”的部分在 Astro 4.x 中,Astro 的内部 Shiki rehype 插件将代码块高亮为 HTML。
Astro 5.0 更新了此插件,将代码块高亮为 hast。这使得 Markdown 和 MDX 的处理更加直接,并提高了项目构建时的性能。然而,这可能会导致现有 Shiki transformers 出现问题。
我应该怎么做?
标题为“我应该怎么做?”的部分如果你正在使用传递给 markdown.shikiConfig.transformers
的 Shiki transformers,你必须确保它们不使用 postprocess
钩子。这个钩子不再对 .md
和 .mdx
文件中的代码块运行。(更多信息请参阅 Shiki 关于 transformer 钩子的文档)。
.mdoc
文件和 Astro 的内置 <Code />
组件中的代码块不使用内部 Shiki rehype 插件,因此不受影响。
变更:Markdown 和 MDX 页面的自动 charset=utf-8
行为
标题为“变更:Markdown 和 MDX 页面的自动 charset=utf-8 行为”的部分在 Astro 4.0 中,Markdown 和 MDX 页面(位于 src/pages/
)会在 Content-Type
头中自动响应 charset=utf-8
,这允许在你的页面中渲染非 ASCII 字符。
Astro 5.0 更新了行为,改为添加 <meta charset="utf-8">
标签,并且仅对不使用 Astro 特殊 layout
frontmatter 属性的页面生效。类似地,对于 MDX 页面,只有当 MDX 内容没有导入一个包裹的 Layout
组件时,Astro 才会添加该标签。
如果你的 Markdown 或 MDX 页面使用了 layout
frontmatter 属性,或者 MDX 页面内容导入了一个包裹的 Layout
组件,那么 HTML 编码将由指定的布局组件来处理,并且 <meta charset="utf-8">
标签将不会被默认添加到你的页面中。
我应该怎么做?
标题为“我应该怎么做?”的部分如果你需要 charset=utf-8
来正确渲染你的页面,请确保你的布局组件包含了 <meta charset="utf-8">
标签。如果你还没有添加,你可能需要添加它。
已更改:在 remark 和 rehype 插件中附加的 Astro 特定元数据
标题为“变更:在 remark 和 rehype 插件中附加的 Astro 特定元数据”的部分在 Astro 4.x 中,附加到 remark 和 rehype 插件中 vfile.data
的 Astro 特定元数据被附加在不同的位置,并且名称不一致。
Astro 5 清理了 API,元数据现在被重命名如下:
vfile.data.__astroHeadings
->vfile.data.astro.headings
vfile.data.imagePaths
->vfile.data.astro.imagePaths
imagePaths
的类型也从 Set<string>
更新为 string[]
。vfile.data.astro.frontmatter
元数据保持不变。
我应该怎么做?
标题为“我应该怎么做?”的部分虽然我们不认为这些是公共 API,但希望重用 Astro 元数据的 remark 和 rehype 插件可以访问它们。如果你正在使用这些 API,请确保在新的位置访问它们。
已更改:图像端点配置
标题为“变更:图片端点配置”的部分在 Astro 4.x 中,你可以在你的 image
配置中设置一个端点用于图片优化。
Astro 5.0 允许你自定义 image.endpoint
配置的 route
和 entrypoint
。在默认路由 /_image
与现有路由或你的本地服务器设置冲突的特定情况下,这可能很有用。
我应该怎么做?
标题为“我应该怎么做?”的部分如果你之前自定义了 image.endpoint
,请将该端点移动到新的 endpoint.entrypoint
属性。可选地,你可以自定义一个 route
。
import { defineConfig } from "astro/config";
defineConfig({ image: { endpoint: './src/image-endpoint.ts', endpoint: { route: "/image", entrypoint: "./src/image_endpoint.ts" } },})
变更:build.client
和 build.server
的解析行为
标题为“变更:build.client 和 build.server 的解析行为”的部分在 Astro v4.x 中,根据文档,build.client
和 build.server
选项应该相对于 outDir
选项进行解析,但它并不总是按预期工作。
Astro 5.0 修复了此行为,使其能够正确地从 outDir
选项进行解析。例如,如果 outDir
设置为 ./dist/nested/
,那么默认情况下:
build.client
将解析为<root>/dist/nested/client/
build.server
将解析为<root>/dist/nested/server/
之前这些值被错误地解析为:
build.client
被解析为<root>/dist/nested/dist/client/
build.server
被解析为<root>/dist/nested/dist/server/
我应该怎么做?
标题为“我应该怎么做?”的部分如果你依赖于之前的构建路径,请确保你的项目代码已更新为新的构建路径。
build
配置选项 的信息。
已更改:配置文件中的 JS 依赖不再由 Vite 处理
标题为“变更:配置文件中的 JS 依赖项不再由 Vite 处理”的部分在 Astro 4.x 中,本地链接的 JS 依赖项(例如 npm link
、在 monorepo 中等)在被 Astro 配置文件导入时,能够使用像 import.meta.glob
这样的 Vite 功能。
Astro 5 更新了 Astro 配置文件的加载流程,以忽略使用 Vite 处理本地链接的 JS 依赖项。导出原始 TypeScript 文件的依赖项不受影响。取而代之的是,这些 JS 依赖项将像 node_modules
中的其他依赖项一样,由 Node.js 运行时正常导入。
进行此项更改是因为之前的行为在集成作者中引起了困惑,他们测试的包在本地可以工作,但发布后却不行。这也限制了 CJS-only 依赖项的使用,因为 Vite 要求代码必须是 ESM。虽然此更改只影响 JS 依赖项,但仍建议包尽可能导出 JavaScript 而不是原始 TypeScript,以防止意外使用 Vite 特定的功能,因为这是 Astro 配置加载流程的一个实现细节。
我应该怎么做?
标题为“我应该怎么做?”的部分在运行你的 Astro 项目之前,请确保你的本地链接的 JS 依赖项已经构建。然后,配置加载应该会像以前一样工作。
变更:由 paginate()
返回的 URL
标题为“变更:由 paginate() 返回的 URL”的部分在 Astro v4.x 中,由 paginate()
返回的 URL(例如 page.url.next
、page.url.first
等)不包括你在 Astro 配置中为 base
设置的值。你必须手动将配置的 base
值前置到 URL 路径。
Astro 5.0 会自动在 page.url
中包含 base
值。
我应该怎么做?
标题为“我应该怎么做?”的部分如果你正在对这些 URL 使用 paginate()
函数,请移除任何现有的 base
值,因为它现在已经为你添加好了:
---export async function getStaticPaths({ paginate }) { const astronautPages = [{ astronaut: 'Neil Armstrong', }, { astronaut: 'Buzz Aldrin', }, { astronaut: 'Sally Ride', }, { astronaut: 'John Glenn', }]; return paginate(astronautPages, { pageSize: 1 });}const { page } = Astro.props;// `base: /'docs'` configured in `astro.config.mjs`const prev = "/docs" + page.url.prev;const prev = page.url.prev;---<a id="prev" href={prev}>Back</a>
已更改:非布尔值的 HTML 属性值
标题为“变更:非布尔值 HTML 属性值”的部分在 Astro v4.x 中,非布尔值 HTML 属性在渲染为 HTML 时可能没有包含它们的值。
Astro v5.0 会将值显式地渲染为 ="true"
或 ="false"
,以匹配浏览器中正确的属性处理方式。
在下面的 .astro
示例中,只有 allowfullscreen
是一个布尔属性:
<!-- `allowfullscreen` is a boolean attribute --><p allowfullscreen={true}></p><p allowfullscreen={false}></p><!-- `inherit` is *not* a boolean attribute --><p inherit={true}></p><p inherit={false}></p><!-- `data-*` attributes are not boolean attributes --><p data-light={true}></p><p data-light={false}></p>
Astro v5.0 现在在渲染非布尔属性的 HTML 时,会保留完整的 data 属性及其值:
<p allowfullscreen></p><p></p>
<p inherit="true"></p><p inherit></p><p inherit="false"></p>
<p data-light></p><p data-light="true"></p><p></p><p data-light="false"></p>
我应该怎么做?
标题为“我应该怎么做?”的部分如果你依赖于属性值,例如,用于定位元素或条件渲染,请更新你的代码以匹配新的非布尔属性值:
el.getAttribute('inherit') === ''el.getAttribute('inherit') === 'false'
el.hasAttribute('data-light')el.dataset.light === 'true'
变更:向 context.locals
添加值
标题为“变更:向 context.locals 添加值”的部分在 Astro 4.x 中,当添加新值时,可以在中间件、API 端点和页面中完全替换整个 locals
对象。
Astro 5.0 要求你将值附加到现有的 locals
对象上,而不是删除它。中间件、API 端点和页面中的 Locals 不能再被完全覆盖。
我应该怎么做?
标题为“我应该怎么做?”的部分在你之前覆盖对象的地方,现在必须改为给它赋值:
ctx.locals = {Object.assign(ctx.locals, { one: 1, two: 2}})
context.locals
中存储数据 的信息。
变更:params
不再被解码
标题为“变更:params 不再被解码”的部分在 Astro v4.x 中,传递给 getStaticPath()
的 params
会自动使用 decodeURIComponent
进行解码。
Astro v5.0 不再解码传递给 getStaticPaths
的 params
的值。如果需要,你必须手动解码它们。
我应该怎么做?
标题为“我应该怎么做?”的部分如果你之前依赖于自动解码,请在传递 params
时使用 decodeURI
。
---export function getStaticPaths() { return [ { params: { id: "%5Bpage%5D" } }, { params: { id: decodeURI("%5Bpage%5D") } }, ]}
const { id } = Astro.params;---
请注意,不鼓励对 getStaticPaths
使用 decodeURIComponent
,因为它会解码比预期更多的字符,例如 /
、?
、#
等。
params
创建动态路由 的信息。
变更:RouteData
类型被 IntegrationsRouteData
替换 (Integrations API)
标题为“变更:RouteData 类型被 IntegrationsRouteData 替换 (Integrations API)”的部分在 Astro v4.x 中,astro:build:ssr
和 astro:build:done
钩子中的 entryPoints
类型是 RouteData
。
Astro v5.0 中,entryPoints
的类型现在是 IntegrationRouteData
,它包含 RouteData
类型的一个子集。字段 isIndex
和 fallbackRoutes
已被移除。
我应该怎么做?
标题为“我应该怎么做?”的部分更新你的适配器,将 entryPoints
的类型从 RouteData
更改为 IntegrationRouteData
。
import type {RouteData} from 'astro';import type {IntegrationRouteData} from "astro"
function useRoute(route: RouteData) {function useRoute(route: IntegrationRouteData) {}
变更:distURL
现在是一个数组 (Integrations API)
标题为“变更:distURL 现在是一个数组 (Integrations API)”的部分在 Astro v4.x 中,RouteData.distURL
是 undefined
或一个 URL
。
Astro v5.0 更新了 IntegrationRouteData.distURL
的形状,使其为 undefined
或一个 URL
数组。这修复了以前的一个错误,因为一个路由可以在磁盘上生成多个文件,尤其是在使用动态路由如 [slug]
或 [...slug]
时。
我应该怎么做?
标题为“我应该怎么做?”的部分更新你的代码以处理作为数组的 IntegrationRouteData.distURL
。
if (route.distURL) { if (route.distURL.endsWith('index.html')) { // do something } for (const url of route.distURL) { if (url.endsWith('index.html')) { // do something } }}
变更:传递给 app.render()
的参数 (Adapter API)
标题为“变更:传递给 app.render() 的参数 (Adapter API)”的部分在 Astro 4.x 中,Adapter API 方法 app.render()
可以接收三个参数:一个强制性的 request
,一个选项对象或一个 routeData
对象,以及 locals
。
Astro 5.0 将后两个参数合并为一个名为 renderOptions
的选项参数。
我应该怎么做?
标题为“我应该怎么做?”的部分将一个对象作为第二个参数传递给 app.render()
,该对象可以包含 routeData
和 locals
作为属性。
const response = await app.render(request, routeData, locals);const response = await app.render(request, {routeData, locals});
变更:supportedAstroFeatures
上的属性 (Adapter API)
标题为“变更:supportedAstroFeatures 上的属性 (Adapter API)”的部分在 Astro 4.x 中,supportedAstroFeatures
允许适配器作者指定他们的集成支持哪些功能,其中包括一个 assets
属性来指定支持 Astro 的哪些图片服务。
Astro 5.0 将此属性替换为一个专用的 sharpImageService
属性,用于确定适配器是否与内置的 sharp 图片服务兼容。
v5.0 还为 supportedAstroFeatures
的不同属性为适配器增加了一个新的 limited
值,表示适配器与该功能兼容,但存在一些限制。这对于那些支持某个功能,但并非在所有情况下或所有选项下都支持的适配器很有用。
此外,适配器的 supportedAstroFeatures
上不同属性的值现在可以是对象,包含 support
和 message
属性。message
属性的内容将在适配器与某个功能不兼容时,在 Astro CLI 中显示一条有用的消息。这对于新的 limited
值尤其有用,可以向用户解释为什么支持是有限的。
我应该怎么做?
标题为“我应该怎么做?”的部分如果你正在使用 assets
属性,请移除它,因为它已不再可用。要指定你的适配器支持内置的 sharp 图片服务,请将其替换为 sharpImageService
。
你可能还希望使用新的 limited
选项更新你支持的功能,并包含一条关于你的适配器支持情况的消息。
supportedAstroFeatures: { assets: { supportKind: "stable", isSharpCompatible: true, isSquooshCompatible: true, }, sharpImageService: { support: "limited", message: 'This adapter supports the built-in sharp image service, but with some limitations.' }}
已移除:开发工具栏应用的已弃用定义形式 (开发工具栏 API)
标题为“移除:已弃用的开发工具栏应用程序定义形状 (Dev Toolbar API)”的部分在 Astro 4.x 中,构建开发工具栏应用程序时,仍然可以使用之前已弃用的 addDevToolbarApp(string);
签名。然后,用于定义应用程序的 id
、title
和 icon
属性通过应用程序 entrypoint
的默认导出提供。
Astro 5.0 完全移除了这个选项,转而采用在集成中定义开发工具栏应用程序时更直观的当前对象形状,这使得 Astro 在工具栏应用程序加载失败时能够提供更好的错误信息。
我应该怎么做?
标题为“我应该怎么做?”的部分如果你正在使用已弃用的形状,请更新你的开发工具栏应用程序以使用新的形状:
// Old shapeaddDevToolbarApp("./my-dev-toolbar-app.mjs");
// New shapeaddDevToolbarApp({ id: "my-app", name: "My App", icon: "<svg>...</svg>", entrypoint: "./my-dev-toolbar-app.mjs",});
export default { id: 'my-dev-toolbar-app', title: 'My Dev Toolbar App', icon: '🚀', init() { // ... }}
移除:在 create-astro
期间配置 Typescript
标题为“移除:在 create-astro 期间配置 Typescript”的部分在 Astro v4.x 中,当使用 create astro
创建新项目时,可以通过回答问题或传递相关的 --typescript
标志并附带所需的 TypeScript 设置,在 Astro 的三种 TypeScript 设置之间进行选择。
Astro 5.0 更新了 create astro
CLI 命令,移除了 TypeScript 问题及其相关的 --typescript
标志。“strict”预设现在是所有通过命令行创建的新项目的默认设置,并且在该时间点无法再进行自定义。但是,仍然可以在 tsconfig.json
中手动更改 TypeScript 模板。
我应该怎么做?
标题为“我应该怎么做?”的部分如果你正在使用 create-astro
的 --typescript
标志,请从你的命令中移除它。
npm create astro@latest -- --template <example-name> --typescript strictnpm create astro@latest -- --template <example-name>
pnpm create astro@latest --template <example-name> --typescript strictpnpm create astro@latest --template <example-name>
yarn create astro --template <example-name> --typescript strictyarn create astro --template <example-name>
社区资源
标题为“社区资源”的部分知道有关 Astro v5.0 的好资源吗?编辑此页并在下方添加链接!
已知问题
标题为“已知问题”的部分请查看 Astro 在 GitHub 上的 issues 以了解任何已报告的问题,或者自己提交一个 issue。
升级指南