跳转到内容

故障排除

Astro 提供了几种不同的工具来帮助你排查和调试代码。

console.log() 是调试 Astro 代码的一种简单而流行的方法。你在哪里编写 console.log() 语句将决定你的调试输出在哪里打印。

---
console.log('Hi! I’m the server. This is logged in the terminal where Astro is running.');
---
<script>
console.log('Hi! I’m the client. This is logged in browser dev console.');
</script>

Astro frontmatter 中的 console.log() 语句将始终输出到运行 Astro CLI 的终端。这是因为 Astro 在服务器上运行,而从不在浏览器中运行。

在 Astro <script> 标签内编写或导入的代码在浏览器中运行。任何 console.log() 语句或其他调试输出都将打印到**你的浏览器控制台**中。

框架组件(如 React 和 Svelte)是独特的:它们默认在服务器端渲染,这意味着 console.log() 的调试输出将在终端中可见。但是,它们也可以在浏览器中进行 hydration,这可能会导致你的调试日志也出现在浏览器中。

这对于调试服务器输出和浏览器中 hydration 后的组件之间的差异非常有用。

为了帮助你调试 Astro 组件,Astro 提供了一个内置的 <Debug /> 组件,它可以将任何值直接渲染到你的组件 HTML 模板中。

该组件提供了一种在客户端检查值的方法,无需任何 JavaScript。这对于在浏览器中进行快速调试非常有用,无需在终端和浏览器之间来回切换。

---
import { Debug } from 'astro:components';
const sum = (a, b) => a + b;
---
<!-- Example: Outputs {answer: 6} to the browser -->
<Debug answer={sum(2, 4)} />

Debug 组件支持多种语法选项,以实现更灵活、更简洁的调试。

---
import { Debug } from 'astro:components';
const sum = (a, b) => a + b;
const answer = sum(2, 4);
---
<!-- Example: All three examples are equivalent. -->
<Debug answer={sum(2, 4)} />
<Debug {{answer: sum(2, 4)}} />
<Debug {answer} />

以下是您可能会在终端中看到的一些常见错误消息、它们的可能含义以及处理方法。请参阅我们的完整错误参考指南,了解您可能遇到的 Astro 错误的完整列表。

在 Astro 组件中,<script> 标签默认作为 JS 模块加载。如果你在标签中包含了 is:inline 指令或任何其他属性,这个默认行为将被移除。

解决方案:如果你给 <script> 标签添加了任何属性,你必须同时添加 type="module" 属性才能使用 import 语句。

状态:预期的 Astro 行为,符合设计。

不确定这是不是你的问题?
检查一下是否有人已经报告了这个问题

当试图在服务器上访问 documentwindow 时会发生此错误。

Astro 组件在服务器上运行,因此你无法在 frontmatter 中访问这些浏览器特有的对象。

框架组件默认在服务器上运行,因此在渲染期间访问 documentwindow 时可能会发生此错误。

解决方案:确定调用 documentwindow 的代码。如果你没有直接使用 documentwindow 但仍然遇到此错误,请检查你导入的任何包是否意在客户端运行。

  • 如果代码在 Astro 组件中,请将其移动到 frontmatter 外部的 <script> 标签中。这会告诉 Astro 在客户端运行此代码,此时 documentwindow 是可用的。

  • 如果代码在框架组件中,请尝试在渲染后使用生命周期方法(例如 React 中的 useEffect(),Vue 中的 onMounted(),以及 Svelte 中的 onMount())来访问这些对象。通过使用像 client:load 这样的 client: 指令,告诉框架组件在客户端进行 hydration,以运行这些生命周期方法。你也可以通过添加 client:only 指令来完全阻止组件在服务器上渲染。

状态:预期的 Astro 行为,符合设计。

当尝试导入或渲染一个无效的、或工作不正常的组件时,可能会抛出此错误。(此特定消息的出现是由于 Astro 中导入 UI 组件的工作方式。)

解决方案:尝试在你正在导入和渲染的任何组件中查找错误,并确保其工作正常。可以考虑从 astro.new 打开一个 Astro 入门模板,并在一个最小的 Astro 项目中仅对你的组件进行故障排除。

状态:预期的 Astro 行为,符合设计。

你可能会在浏览器控制台中看到以下错误日志

拒绝执行内联脚本,因为它违反了以下内容安全策略指令:...

这意味着你网站的内容安全策略(CSP)不允许运行内联 <script> 标签,而 Astro 默认会输出这种标签。

解决方案: 更新你的 CSP 以包含 script-src: 'unsafe-inline' 来允许内联脚本运行。或者,你可以使用第三方集成,如 astro-shield 来为你生成 CSP 头部。

首先,检查你是否在你的 .astro 组件脚本.mdx 文件中**导入了该组件**。

然后检查你的 import 语句

  • 你的 import 是否链接到了错误的地方?(检查你的导入路径。)

  • 你的 import 是否与导入的组件同名?(检查你的组件名称,并确保它遵循 .astro 语法。)

  • 你在 import 中包含文件扩展名了吗?(检查你导入的文件是否包含扩展名。例如 .astro.md.vue.svelte。注意:仅 .js(x).ts(x) 文件需要文件扩展名。)

如果你的组件正在渲染(见上文),但对用户交互没有响应,那么你可能缺少一个 client:* 指令来 hydrate 你的组件。

默认情况下,UI 框架组件不会在客户端进行 hydrate。如果没有提供 client:* 指令,它的 HTML 会被渲染到页面上,但没有 JavaScript。

如果你在启动 Astro 时看到 "Cannot find package 'react'"(或类似)的警告,这意味着你需要将该包安装到你的项目中。并非所有的包管理器都会自动为你安装 peer dependencies。如果你使用 Node v16+ 和 npm,则无需担心此部分。

例如,React 是 @astrojs/react 集成的 peer dependency。这意味着你应该在安装集成的同时安装官方的 reactreact-dom 包。然后,该集成将自动从这些包中提取。

终端窗口
# Example: Install integrations and frameworks together
npm install @astrojs/react react react-dom

有关向 Astro 添加框架渲染器、CSS 工具和其他包的说明,请参阅 Astro 的集成指南

Yarn 2+(又名 Berry)使用一种称为 Plug'n'Play (PnP) 的技术来存储和管理 Node 模块,这在使用 create astro 初始化新的 Astro 项目或在使用 Astro 时可能会导致问题。一个解决方法是在 .yarnrc.yml 中将 nodeLinker 属性设置为 node-modules

.yarnrc.yml
nodeLinker: "node-modules"

在 monorepo 设置中使用 Astro 时,项目依赖项应添加到每个项目自己的 package.json 文件中。

但是,你可能也想在 monorepo 的根目录中使用 Astro(例如,Nx 项目建议在根目录安装依赖项)。在这种情况下,手动将 Astro 相关的依赖项(例如 @astrojs/vueastro-component-lib)添加到 Astro 配置的 vite.ssr.noExternal 部分,以确保这些依赖项被正确安装和打包。

astro.config.mjs
import { defineConfig } from 'astro/config'
export default defineConfig({
vite: {
ssr: {
noExternal: [
'@astrojs/vue',
'astro-component-lib',
]
}
}
})

在 Astro 中,使用 <head> 标签就像使用任何其他 HTML 标签一样:它不会被移动到页面顶部或与现有的 <head> 合并。因此,你通常只想在整个页面中包含一个 <head> 标签。我们建议在布局组件中编写这一个 <head> 及其内容。

你可能会注意到,即使导入的组件没有出现在最终输出中,它的 <style> 标签也包含在你的 HTML 源代码中。例如,对于未显示的条件渲染组件,就会发生这种情况。

Astro 的构建过程基于模块图:一旦一个组件被包含在模板中,它的 <style> 标签就会被处理、优化和打包,无论它是否出现在最终输出中。

某些字符在 Markdown 中有特殊含义。如果你想显示它们,可能需要使用不同的语法。为此,你可以使用这些字符的 HTML 实体来代替。

例如,为防止 < 被解释为 HTML 元素的开头,请写成 &lt;

在对代码进行故障排除时,创建一个可以共享问题的**最小化可复现仓库**会很有帮助。这是一个更小、更简化的 Astro 项目,用于演示你的问题。在一个新项目中拥有一个可工作的复现,有助于确认这是一个可重复的问题,而不是由你的个人环境或现有项目中的其他因素引起的。

在我们的支持帖中寻求帮助时,共享一个最小化可复现仓库很有帮助,并且在向 Astro 提交错误报告时通常是必需的。

你可以使用 astro.new 一键创建一个新的 Astro 项目。对于最小化可复现仓库,我们强烈建议从在 StackBlitz 中运行的最小(空)示例开始,并使用尽可能少的额外代码。

StackBlitz 将在浏览器中运行这个 Astro 项目,独立于你的本地环境。它还会为你提供一个可共享的链接,以便任何 Astro 维护者或支持团队成员都可以在他们自己的本地环境之外查看你的最小化可复现仓库。这意味着每个人都在查看完全相同的项目,具有相同的配置和依赖项。这使得其他人很容易帮助你排查代码问题。如果问题是可复现的,它能让你验证问题在于 Astro 代码本身,你可以放心地提交错误报告。

请注意,并非所有问题都可以在 StackBlitz 中复现。例如,你的问题可能依赖于特定的环境或包管理器,或者可能涉及 HTML 流式传输,而 StackBlitz 不支持此功能。在这种情况下,请使用 CLI 创建一个新的最小(空)Astro 项目,复现问题,并将其上传到 GitHub 仓库。不要共享 StackBlitz URL,而是提供你的最小化可复现仓库的 GitHub 仓库链接。

一旦你的空项目设置好,就按照步骤复现问题。这可能包括添加包、更改配置和编写代码。

你应该只添加复现问题所需的最少量代码。不要复现你现有项目的其他元素,并删除所有与问题不直接相关的代码。

如果你的问题可以被复现,那么就该创建一个 issue 并提交错误报告了!

前往 GitHub 上相应的 Astro 仓库并开启一个新的 issue。大多数仓库都有一个 issue 模板,会要求你回答问题或提供信息才能提交。遵循这些模板非常重要,因为如果你不提供我们需要的信息,我们就得向你索要……这样就没人能处理你的 issue 了!

请附上你在 StackBlitz 上的最小化可复现仓库链接(或必要时附上 GitHub 仓库链接)。首先描述预期行为与实际行为的对比,为问题提供背景。然后,提供清晰的、分步的说明,如何在 Astro 项目中复现该问题。

来我们的 Discord 上聊天,并在 #support 论坛频道中解释你的问题。我们总是很乐意提供帮助!

访问 Astro 当前的开放 Issue,看看你是否遇到了已知问题,或者提交一个错误报告。

你也可以访问 RFC 讨论区,看看你是否发现了 Astro 的已知限制,并检查是否有与你的用例相关的当前提案。

贡献 社区 赞助