跳转到内容

导入参考

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

Astro 开箱即用地支持以下文件类型

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

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

你可以将任何静态资源放置在项目的public/ 目录中,Astro 会将其原封不动地直接复制到最终的构建产物中。public/ 目录中的文件不会被 Astro 构建或打包,这意味着任何类型的文件都受支持。

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

// To link to /public/reports/annual/2024.pdf
Download the <a href="/reports/annual/2024.pdf">2024 annual statement as a PDF</a>.
// To display /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。

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

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

Astro 本身不执行任何类型检查。 类型检查应该在 Astro 之外进行,可以由你的 IDE 或通过一个单独的脚本来完成。对于 Astro 文件的类型检查,提供了 astro check 命令

阅读更多关于Astro 中的 TypeScript 支持

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

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

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

// Load the JSON object via the default export
import json from './data.json';

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

// Load and inject 'style.css' onto the page
import './style.css';

Astro 支持将 CSS 文件直接导入到你的应用程序中。导入的样式不公开任何导出,但导入一个 CSS 文件会自动将这些样式添加到页面上。这默认适用于所有 CSS 文件,并且可以通过插件支持像 Sass 和 Less 这样的编译到 CSS 的语言。

样式指南中阅读更多关于高级 CSS 导入用例,例如 CSS 文件的直接 URL 引用或将 CSS 作为字符串导入。
// 1. Converts './style.module.css' classnames to unique, scoped values.
// 2. Returns an object mapping the original classnames to their final, scoped value.
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 Modules。和任何 CSS 文件一样,导入它会自动将 CSS 应用到页面上。然而,CSS Modules 会导出一个特殊的默认 styles 对象,它将你的原始类名映射到唯一的标识符。

CSS Modules 通过为你的样式表生成唯一的类名,帮助你在前端强制实现组件作用域和隔离。

import imgReference from './image.png'; // imgReference === '/src/image.png'
import svgReference from './image.svg'; // svgReference === '/src/image.svg'
import txtReference from './words.txt'; // txtReference === '/src/words.txt'
// This example uses JSX, but you can use import references with any framework.
<img src={imgReference.src} alt="image description" />;

所有其他未明确提及的资源都可以通过 ESM import 导入,并将返回一个指向最终构建资源的 URL 引用。这对于通过 URL 引用非 JS 资源非常有用,比如创建一个 src 属性指向该图像的图片元素。

将图片放在 public/ 文件夹中也很有用,正如在项目结构页面上解释的那样。

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

别名是为你的导入创建快捷方式的一种方法。

别名可以帮助改善在具有许多目录或相对导入的代码库中的开发体验。

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

在这个例子中,开发者需要理解 src/pages/about/company.astrosrc/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
---
// imports all files that end with `.md` in `./src/pages/post/`
const matches = import.meta.glob('../pages/post/*.md', { eager: true });
const posts = Object.values(matches);
---
<!-- Renders an <article> for the first 5 blog posts -->
<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
---
// imports all files that end with `.astro` in `./src/components/`
const components = Object.values(import.meta.glob('../components/*.astro', { eager: true }));
---
<!-- Display all of our components -->
{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>> {
/* Any data specified in this file's YAML/TOML frontmatter */
frontmatter: T;
/* The absolute file path of this file */
file: string;
/* The rendered path of this file */
url: string | undefined;
/* Astro Component that renders the contents of this file */
Content: AstroComponentFactory;
/** (Markdown only) Raw Markdown file content, excluding layout HTML and YAML/TOML frontmatter */
rawContent(): string;
/** (Markdown only) Markdown file compiled to HTML, excluding layout HTML */
compiledContent(): string;
/* Function that returns an array of the h1...h6 elements in this file */
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 {
/* The file path of this file */
file: string;
/* The URL for this file (if it is in the pages directory) */
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 模式语法的信息.

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

// Loads and initializes the requested WASM file
const wasm = await WebAssembly.instantiateStreaming(fetch('/example.wasm'));

Astro 支持使用浏览器的 WebAssembly API 直接将 WASM 文件加载到你的应用程序中。

Astro 支持 Node.js 内置模块,但有一些限制,需要使用 Node 新的 node: 前缀。开发和生产环境之间可能存在差异,某些功能可能与按需渲染不兼容。一些适配器也可能与这些内置模块不兼容,或者需要配置以支持其子集(例如,Cloudflare WorkersDeno)。

以下示例从 Node 导入 util 模块来解析媒体类型(MIME)

src/components/MyComponent.astro
---
// Example: import the "util" built-in from Node.js
import util from 'node:util';
export interface Props {
mimeType: string,
}
const mime = new util.MIMEType(Astro.props.mimeType)
---
<span>Type: {mime.type}</span>
<span>SubType: {mime.subtype}</span>

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

贡献 社区 赞助