跳转到内容

导入参考

Astro 无需配置即支持大多数静态资源。你可以在项目的任何地方使用 import 语句(包括 Astro frontmatter 脚本),Astro 将在最终构建中内置优化后的静态资源副本。在 CSS 和 <style> 标签中也可以使用 @import

下面的文件类型 Astro 开箱即用:

  • Astro 组件 (.astro)
  • Markdown (.md.markdown,等等)
  • JavaScript (.js.mjs)
  • TypeScript (.ts)
  • NPM 包
  • JSON (.json)
  • CSS (.css)
  • CSS 模块 (.module.css)
  • 图片和资源 (.svg.jpg.png,等等。)

此外,你可以扩展 Astro 以添加对不同 UI 框架的支持,如 React、Svelte 和 Vue 组件。你还可以安装 Astro MDX 集成Astro Markdoc 集成 在项目中使用 .mdx 或者 .mdoc 文件。

你可以将任何静态资源放在项目的 public/ 目录中,Astro 将直接将其复制到最终构建中,而不会对其进行任何处理。public/ 文件不会被 Astro 构建或打包,这意味着支持任何类型的文件。

你可以直接在模板中通过 URL 路径引用 public/ 文件。

// 链接到 /public/reports/annual/2024.pdf
Download the <a href="/reports/annual/2024.pdf">2024 annual statement as a PDF</a>.
// 显示 /public/assets/cats/ginger.jpg
<img src="/assets/cats/ginger.jpg" alt="An orange cat sleeping on a bed.">

Astro 使用 ESM,它是浏览器中支持的相同 importexport 语法。

import { getUser } from './user.js';

可以使用普通的 ESM importexport 语法来导入 JavaScript。它在 Node.js 和浏览器中和预期保持一致。

import { getUser } from './user';
import type { UserType } from './user';

Astro 内置对 TypeScript 的支持。你可以在 Astro 项目中直接导入 .ts.tsx 文件,甚至可以直接在 Astro 组件脚本和任意 script 标签 中编写 TypeScript 代码。

Astro 本身不进行任何类型检查。类型检查应该在 Astro 之外进行或由 IDE 或通过一个单独的脚本来处理。Astro VSCode 扩展 会自动为打开的文件中提供 TypeScript 提示和错误警告。或使用 astro check 命令 检查 Astro 文件的类型。

了解更多关于 Astro 中的 TypeScript 支持 的内容。

如果你安装了一个 NPM 包,你可以在 Astro 中导入它。

---
import { Icon } from 'astro-icon';
---

如果一个包使用了旧的格式发布,Astro 将尝试将包转换为 ESM,以便 import 语句可以正常工作。在某些情况下,你可能需要调整你的 vite 配置 以使其正常工作。

// 使用默认导入加载 JSON 对象
import json from './data.json';

Astro 支持直接在应用程序中导入 JSON 文件。导入文件会通过默认导入返回完整的 JSON 对象。

// 加载并将 'style.css' 注入到页面上。
import './style.css';

Astro 支持直接在应用程序中导入 CSS 文件。导入的样式没有暴露出口,但导入样式会自动将这些样式添加到页面中。它默认支持所有 CSS 文件,并且可以通过插件支持 CSS 编译语言,如 Sass & Less。

样式指南 中阅读有关高级 CSS 导入用例的更多信息,例如直接通过 URL 引用 CSS 文件,或将 CSS 作为字符串导入。
// 1. 将 './style.module.css' 转换为类名唯一、有范围的值。
// 2. 返回对象,并将原始类名映射到其最终范围值的。
import styles from './style.module.css';
// This example uses JSX, but you can use CSS Modules with any framework.
return <div className={styles.error}>Your Error Message</div>;

Astro 支持使用 [name].module.css 命名约定的 CSS 模块。像导入任何 CSS 文件一样,导入 CSS 会应用到页面。然而,CSS 模块默认导出特殊的 styles 对象,并将你的原始类名映射到唯一的标识符。

CSS 模块帮助你在前端强制执行组件样式隔离,并生成唯一的样式表类名。

import imgReference from './image.png'; // img === '/src/image.png'
import svgReference from './image.svg'; // svg === '/src/image.svg'
import txtReference from './words.txt'; // txt === '/src/words.txt'
// 这个例子使用 JSX,但你可以在任何框架下使用导入引用。
<img src={imgReference.src} alt="image description" />;

所有其他没有明确提到的资源可以通过 ESM 的 import 语句导入,并将返回最终构建中的资源引用连接。这对使用链接引用非 JS 资源很有用,比如创建一个带有 src 属性的图片元素指向该图片。

将图片放在 public/ 文件夹中也很有用,这在项目结构页面中有所解释。

有关附加 Vite 导入参数(例如 ?url?raw)的更多信息,请参阅 Vite 静态资源处理指南

别名可以用于创建简洁的导入。

别名有助于改善在项目中大量使用绝对或相对引用的体验。

src/pages/about/company.astro
---
import Button from '../../components/controls/Button.astro';
import logoUrl from '../../assets/logo.png?url';
---

在这个示例中,开发者需要理解 src/pages/about/company.astro, src/components/controls/Button.astrosrc/assets/logo.png 间的关系。如果移动了 company.astro 文件,那么这些导入也都需要更新。

你可以在 tsconfig.json 中添加导入别名。

tsconfig.json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@components/*": ["src/components/*"],
"@assets/*": ["src/assets/*"]
}
}
}

在这个配置更改完之后,开发服务器会自动重启。然后,你可以在项目中的任何地方使用这些别名进行导入:

src/pages/about/company.astro
---
import Button from '@components/controls/Button.astro';
import logoUrl from '@assets/logo.png?url';
---

VS Code 或其他编辑器会自动集成这些别名。

Vite 的 import.meta.glob() 是一种使用 glob 模式一次导入多个文件来查找匹配文件路径的方法。

import.meta.glob() 采用与你要导入的文件匹配的 glob 模式,并返回每个匹配文件的导出的数组。要预先加载所有匹配的模块,请传递 eager: true 作为第二个参数。

src/components/my-component.astro
---
// 导入`./src/pages/post/` 中所有以 `.md` 结尾的文件
const matches = import.meta.glob('../pages/post/*.md', { eager: true });
const posts = Object.values(matches);
---
<!-- 把前 5 篇博客文章渲染成 <article> -->
<div>
{posts.slice(0, 4).map((post) => (
<article>
<h2>{post.frontmatter.title}</h2>
<p>{post.frontmatter.description}</p>
<a href={post.url}>Read more</a>
</article>
))}
</div>

使用 import.meta.glob 导入的 Astro 组件的类型为 AstroInstance。你可以使用其 default 属性渲染每个组件实例:

src/pages/component-library.astro
---
// 导入`./src/components/` 中所有以 `.astro` 结尾的文件
const components = Object.values(import.meta.glob('../components/*.astro', { eager: true }));
---
<!-- 展示所有组件-->
{components.map((component) => (
<div>
<component.default size={24} />
</div>
))}

Vite 的 import.meta.glob() 函数仅支持静态字符串字面量。它不支持动态变量和字符串插值。

一种常见的解决方法是导入一个包含所有你需要的文件的更大的文件集,然后对它们进行过滤:

src/components/featured.astro
---
const { postSlug } = Astro.props;
const pathToMyFeaturedPost = `src/pages/blog/${postSlug}.md`;
const posts = Object.values(import.meta.glob("../pages/blog/*.md", { eager: true }));
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>

使用 import.meta.glob() 加载的 Markdown 文件返回以下 MarkdownInstance 接口:

export interface MarkdownInstance<T extends Record<string, any>> {
/* 该文件的 YAML frontmatter 中指定的任何数据 */
frontmatter: T;
/* 该文件的绝对文件路径 */
file: string;
/* 该文件的渲染路径 */
url: string | undefined;
/* 渲染此文件内容的 Astro 组件 */
Content: AstroComponentFactory;
/** (仅限 Markdown)原始 Markdown 文件内容,不包括布局 HTML 和 YAML frontmatter */
rawContent(): string;
/** (仅限 Markdown)将 Markdown 文件编译为 HTML,不包括布局 HTML */
compiledContent(): string;
/* 返回此文件中的 h1...h6 元素数组的函数 */
getHeadings(): Promise<{ depth: number; slug: string; text: string }[]>;
default: AstroComponentFactory;
}

你可以选择使用 TypeScript 泛型为 frontmatter 变量提供类型。

---
import type { MarkdownInstance } from 'astro';
interface Frontmatter {
title: string;
description?: string;
}
const posts = Object.values(import.meta.glob<MarkdownInstance<Frontmatter>>('./posts/**/*.md', { eager: true }));
---
<ul>
{posts.map(post => <li>{post.frontmatter.title}</li>)}
</ul>

Astro 文件具有以下接口:

export interface AstroInstance {
/* 该文件的文件路径 */
file: string;
/* 如果文件在 pages 目录中,则为此文件的 URL */
url: string | undefined;
default: AstroComponentFactory;
}

其他文件可能有各种不同的接口,但是如果你确切地知道一个未识别的文件类型包含什么,import.meta.glob() 接受一个 TypeScript 泛型。

---
interface CustomDataFile {
default: Record<string, any>;
}
const data = import.meta.glob<CustomDataFile>('../data/**/*.js');
---

glob 模式是一个支持特殊通配符的文件路径。用于一次引用项目中的多个文件。

例如,glob 模式 ./pages/**/*.{md,mdx} 从 pages 子目录开始,查找其所有子目录(/**),并匹配以 .md.mdx 结尾的任何文件名(.{md,mdx})。

要与 import.meta.glob() 一起使用,glob 模式必须是字符串字面量,并且不能包含任何变量。

此外,glob 模式必须以以下之一开头:

  • ./(从当前目录开始)
  • ../(从父目录开始)
  • /(从项目根目录开始)

阅读更多关于 glob 模式语法

import.meta.glob() vs getCollection()

段落标题 import.meta.glob() vs getCollection()

内容集合 提供用于加载多个文件的 getCollection() API 代替 import.meta.glob()。如果你的内容文件 (例如 Markdown, MDX, Markdoc) 位于src/content/ 目录内的集合中,使用 getCollection() 查询集合并返回内容条目。

// 加载并初始化所请求的 WASM 文件
const wasm = await WebAssembly.instantiateStreaming(fetch('/example.wasm'));

Astro 支持使用浏览器的 WebAssembly API 直接在应用程序中 WASM 文件。

我们鼓励 Astro 用户尽可能避免使用 Node.js 内置模块(fspath 等)。Astro 兼容多个运行时使用 适配器 (EN)。这包括 DenoCloudflare Workers,它们不支持 Node 内置模块,例如 fs

我们致力于为常用的 Node.js 内置模块提供 Astro 化的替代品,不过现在还没有实现。因此,如果你真的需要,我们不会阻止你使用这些内置模块。Astro 支持使用较新 node: 前缀来支持 Node.js 内置模块。例如,如果你想读取一个文件,你可以这样做:

src/components/MyComponent.astro
---
// 示例:从 Node.js 中导入内置模块 "fs/promises"
import fs from 'node:fs/promises';
const url = new URL('../../package.json', import.meta.url);
const json = await fs.readFile(url, 'utf-8');
const data = JSON.parse(json);
---
<span>Version: {data.version}</span>

使用 Vite 和兼容的 Rollup 插件,你可以导入 Astro 原生不支持的文件类型。在 Vite 文档的 查找插件 部分了解你需要的插件。

贡献 社区 赞助