跳转到内容

故障排除

Astro 提供了几个不同的工具来帮助你排除故障和调试你的代码。

console.log() 是一种简单但普遍的调试 Astro 代码的方法。你写 console.log() 语句的位置将决定你的调试输出被打印在哪里。

---
console.log('Hi! 我是服务器。这是在运行 Astro 的终端中记录的。');
---
<script>
console.log('Hi! 我是客户端。这是在浏览器的开发控制台中记录的');
</script>

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

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

框架组件(如 React 和 Svelte)较为特殊。它们默认在服务器端渲染,这意味着 console.log() 的调试输出将显示到终端中。然而,它们也可能会在浏览器中被激活,导致你的调试日志也出现在浏览器中。

这对于调试 SSR 输出和浏览器中的激活组件之间的差异非常有用。

为了帮助你调试 Astro 组件,Astro 提供了内置的 <Debug /> 组件,你可以用它把任意值直接渲染到你的 HTML 模板中。这对于在浏览器中进行快速调试是很有用的,而不必在终端和浏览器之间来回切换。

---
import { Debug } from 'astro:components';
const sum = (a, b) => a + b;
---
<!-- 示例:在浏览器中输出 {answer: 6} -->
<Debug answer={sum(2, 4)} />

Debug 组件支持多种语法,使调试更加灵活和简明。

---
import { Debug } from 'astro:components';
const sum = (a, b) => a + b;
const answer = sum(2, 4);
---
<!-- 示例:三者等效-->
<Debug answer={sum(2, 4)} />
<Debug {{answer: sum(2, 4)}} />
<Debug {answer} />

下面是你在终端可能会看到的一些常见错误信息,包括它们可能的含义及解决方案。查阅我们的 完整错误参考指南,了解你可能遇到的所有 Astro 错误。

Cannot use import statement outside a module(不能在模块外使用导入语句)

段落标题 Cannot use import statement outside a module(不能在模块外使用导入语句)

在 Astro 组件中,<script> 标签会被挂起并默认作为 JS 模块加载。如果你在标签中包含了 is:inline 指令或任何其他属性,将不使用该行为。

解决方案:如果你在 <script> 标签中添加了任何属性,你也必须添加 type="module" 属性,以便能够使用导入语句。

状态:预期 Astro 行为。

不确定这是你的问题? 检查一下是否有其他人报告过这个问题!

document (or window) is not defined(documentwindow 对象未定义)

段落标题 document (or window) is not defined(document 或 window 对象未定义)

当试图在服务器上访问 documentwindow 时,会出现这个错误。

Astro 组件是在服务器上运行的,因此你不能在 frontmatter (代码栅栏)中访问这些浏览器特定的对象。

框架组件默认是在服务器上运行的,因此在渲染期间访问 documentwindow 时可能会出现这个错误。

解决方案:定位到代码中调用 documentwindow 的位置。如果你没有直接调用 documentwindow,但报错依旧存在,请检查你引用的包是否是在客户端运行的。

  • 如果该代码位于 Astro 组件中,将其移动到 frontmatter (代码栅栏)之外的 <script> 标签中。这会告诉 Astro 在客户端运行该代码,documentwindow 在客户端是可用的。

  • 如果代码位于框架组件中,请尝试使用生命周期方法(例如 React 中的 useEffect()、Vue 中的 onMounted() 和 Svelte 中的 onMount())在渲染后访问这些对象。通过使用 client: 指令(例如 client:load)来告诉框架组件在客户端进行水合,从而运行这些生命周期方法。你还可以通过添加 client:only 指令来防止组件在服务器上进行渲染。

状态:预期 Astro 行为。

Expected a default export(期待默认导出)

段落标题 Expected a default export(期待默认导出)

当试图导入或渲染一个无效的、无法正常工作的组件时,会出现这个错误(该错误信息是由 Astro 中导入 UI 组件的方式造成的)。

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

状态:预期 Astro 行为。

Refused to execute inline script(拒绝执行内联脚本)

段落标题 Refused to execute inline script(拒绝执行内联脚本)

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

Refused to execute inline script because it violates the following Content Security Policy directive: … (拒绝执行内联脚本,因为它违反了以下内容安全策略指令)

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

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

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

然后检查你的导入语句。

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

  • 你的导入与导入的组件有名称相同吗?(检查你的组件名称和它是否遵循 .astro 语法

  • 你在导入时是否包含了扩展名?(检查你导入的文件是否包含扩展名。例如:.astro.md.vue.svelte。注意:只有.js(x).ts(x) 文件不需要在导入语句中加入扩展名。)

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

默认情况下,UI 框架组件在客户端不会激活 。如果没有提供 client:* 指令,它的 HTML 将直接渲染到页面上,而无需 JavaScript。

无法找到软件包 ‘X’

段落标题 无法找到软件包 ‘X’

如果你在启动 Astro 时看到 "Cannot find package 'react'" 或其他类似警告,这意味着你需要手动安装该包。不是所有的包管理器都会自动为你安装对等依赖。如果你是在 Node v16 以上并且使用 npm,则不需要担心。

例如,React 是 @astrojs/react 集成的对等依赖。这意味着除安装集成外还需安装官方的 reactreact-dom 包。然后,该集成将自动从这些包中提取。

Terminal window
# 示例:同时安装集成和框架
npm install @astrojs/react react react-dom

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

Astro.glob() - 没有找到匹配项

段落标题 Astro.glob() - 没有找到匹配项

当使用Astro.glob()导入文件时,请确保使用正确的glob语法,以匹配所有你需要的文件。

例如,在 src/pages/index.astro 中使用 .../components/**/*.js 来导入以下两个文件:

  • src/components/MyComponent.js
  • src/components/includes/MyOtherComponent.js

Astro.glob() 不支持动态变量和字符串插值。

这不是 Astro 的 bug。这是由于 Vite 的 import.meta.glob() 函数的限制,它只支持静态字符串字面量。

通常可以使用 Astro.glob() 导入包括所有你需要的文件集,然后对其进行过滤,以此来解决这个问题。

src/components/featured.astro
---
const { postSlug } = Astro.props
const pathToMyFeaturedPost = `src/pages/blog/${postSlug}.md`
const posts = await Astro.glob('../pages/blog/*.md');
const myFeaturedPost = posts.find(post => post.file.includes(pathToMyFeaturedPost));
---
<p>
Take a look at my favorite post, <a href={myFeaturedPost.url}>{myFeaturedPost.frontmatter.title}</a>!
</p>

和 Yarn 2+(Berry)一起使用 Astro

段落标题 和 Yarn 2+(Berry)一起使用 Astro

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

.yarnrc.yml
nodeLinker: "node-modules"

在单一代码库中为 Astro 添加依赖

段落标题 在单一代码库中为 Astro 添加依赖

在使用 Astro 进行单一代码库设置时,应该在每个项目自己的 package.json 文件中添加项目依赖。

然而,你可能也希望在单一代码库的根目录中使用 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> 和其内容。

你可能会注意到,即使组件不出现在最终输出中,导入的组件的 <script><style> 标签也会包含在 HTML 源中。例如,这样的情况会发生在未展示的条件渲染组件中。

Astro 的构建过程是基于模块图的:一旦组件包含在模板中,它的 <script><style> 标签就会被处理、优化和打包,无论该组件是否出现在最终输出中。当使用 is:inline 指令时,该规则将不适用于脚本。

当你排查代码时,创建一个 最小化复现 的问题可以很有帮助,你可以将其分享出来。这是一个更小、更简化的 Astro 项目,用于演示你遇到的问题。在一个新的项目中一个有效的复现有助于确认这是否是一个可重复的问题,而不是由于你个人环境或现有项目中的其他因素引起的。

在我们的技术支持论坛寻求帮助时,分享一个最小化复现对于解决问题非常有帮助,并且这在向 Astro 提交错误报告时通常是必需的。

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

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

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

当你的空项目设置完成后,按照以下步骤复现问题,包括添加包、更改配置和编写代码。

你应该只编写最少量的必要代码来复现问题。不要复制你现有项目的其他元素,并且删除所有与问题无关的代码。

如果你的问题可以重现,那么现在是时候创建一个问题并提交一个 bug 报告了!

前往 GitHub上 相应的 Astro 代码库去创建一个新的问题。大多数代码库都有一个问题模板,会询问问题或要求提供信息以便提交报告。遵循这些模板很重要,因为如果你没有提供我们需要的信息,我们就不得不向你询问……这样会导致你的问题得不到及时处理!

在问题报告中贴上你在 StackBlitz 上的最小化复现链接(或必要时提供 GitHub 代码库库的链接)。首先,描述预期的行为与实际行为之间的差异,为问题提供上下文信息。接着,提供清晰的逐步说明,以在Astro项目中复现该问题。

请在 Discord 上与我们交流,并在 #support 频道中解释你的问题。我们很乐于提供帮助!

查看当前的 Astro 中打开的 issues,看看你是否遇到了已知的问题,也可以提交错误报告。

你还可以访问 RFC 讨论,看看你是否发现了 Astro 的已知限制,并检查是否有与你的使用情况相关的提案。

贡献

你有什么想法?

社区