Skip to content

从 Gatsby 迁移

以下是一些可帮助你入门的关键概念和迁移策略。使用我们的其余文档和 Discord 社区 继续前进!

¥Here are some key concepts and migration strategies to help you get started. Use the rest of our docs and our Discord community to keep going!

Gatsby 和 Astro 之间的主要相似之处

Section titled Gatsby 和 Astro 之间的主要相似之处

¥Key Similarities between Gatsby and Astro

Gatsby 和 Astro 有一些相似之处,可以帮助你迁移项目:

¥Gatsby and Astro share some similarities that will help you migrate your project:

Gatsby 和 Astro 之间的主要区别

Section titled Gatsby 和 Astro 之间的主要区别

¥Key Differences between Gatsby and Astro

当你在 Astro 中重建 Gatsby 站点时,你会注意到一些重要的差异:

¥When you rebuild your Gatsby site in Astro, you will notice some important differences:

  • Gatsby 项目是 React 单页应用,并使用 index.js 作为项目的根目录。Astro 项目是多页面网站,index.astro 是你的主页。

  • Astro 组件 未编写为返回页面模板的导出函数。相反,你将把代码拆分为 JavaScript 的 “代码围栏” 和专门用于你生成的 HTML 的正文。

  • Local file data: Gatsby uses GraphQL to retrieve data from your project files. Astro uses ESM imports and top-level await functions (e.g. Astro.glob()getCollection())从你的项目文件中导入数据。你可以手动将 GraphQL 添加到 Astro 项目,但默认情况下不包含它。

¥Convert your Gatsby Project

每个项目迁移看起来都会有所不同,但是从 Gatsby 转换到 Astro 时你将执行一些常见操作。

¥Each project migration will look different, but there are some common actions you will perform when converting from Gatsby to Astro.

创建一个新的 Astro 项目

Section titled 创建一个新的 Astro 项目

¥Create a new Astro project

使用包管理器的 create astro 命令来启动 Astro 的 CLI 向导或从 Astro 主题展示 中选择社区主题。

¥Use the create astro command for your package manager to launch Astro’s CLI wizard or choose a community theme from the Astro Theme Showcase.

你可以将 --template 参数传递给 create astro 命令,以使用我们的官方启动器之一启动新的 Astro 项目(例如 docsblogportfolio)。或者,你可以 从 GitHub 上任何现有的 Astro 存储库启动一个新项目

¥You can pass a --template argument to the create astro command to start a new Astro project with one of our official starters (e.g. docs, blog, portfolio). Or, you can start a new project from any existing Astro repository on GitHub.

Terminal window
# launch the Astro CLI Wizard
npm create astro@latest
# create a new project with an official example
npm create astro@latest -- --template <example-name>

然后,将现有的 Gatsby 项目文件复制到新的 Astro 项目到 src 之外的单独文件夹中。

¥Then, copy your existing Gatsby project files over to your new Astro project into a separate folder outside of src.

¥Install integrations (optional)

你可能会发现安装一些 Astro 的可选集成 以便在将 Gatsby 项目转换为 Astro 时使用非常有用:

¥You may find it useful to install some of Astro’s optional integrations to use while converting your Gatsby project to Astro:

  • @astrojs/react:在新的 Astro 站点中重用一些现有的 React UI 组件或继续使用 React 组件进行编写。

  • @astrojs/mdx:从 Gatsby 项目中引入现有的 MDX 文件,或者在新的 Astro 站点中使用 MDX。

¥Put your code in src

Astro 的项目结构 之后:

¥Following Astro’s project structure:

  1. Delete Gatsby’s public/ folder.

    Gatsby uses the public/ directory for its build output, so you can safely discard this folder. You will no longer need a built version of your Gatsby site. (Astro uses dist/ by default for the build output.)

  2. Rename Gatsby’s static/ folder to public/, and use it as Astro’s public/ folder.

    Astro uses a folder called public/ for static assets. You can alternatively copy the contents of static/ into your existing Astro public/ folder.

  3. Copy or Move Gatsby’s other files and folders (e.g. components, pages, etc.) as needed into your Astro src/ folder as you rebuild your site, following Astro’s project structure.

    Astro’s src/pages/ folder is a special folder used for file-based routing to create your site’s pages and posts from .astro, .md and .mdx files. You will not have to configure any routing behavior for your Astro, Markdown, and MDX files.

    All other folders are optional, and you can organize the contents of your src/ folder any way you like. Other common folders in Astro projects include src/layouts/, src/components, src/styles, and src/scripts.

提示:将 JSX 文件转换为 .astro 文件

Section titled 提示:将 JSX 文件转换为 .astro 文件

¥Tips: Convert JSX files to .astro files

以下是将 Gatsby .js 组件转换为 .astro 组件的一些技巧:

¥Here are some tips for converting a Gatsby .js component into a .astro component:

  1. 仅使用现有 Gatsby 组件函数的 return() 作为 HTML 模板。

  2. 更改任何 Gatsby 或 JSX 语法到 Astro 语法 或 HTML Web 标准。例如,这包括 <Link to="">{children}className

  3. 将任何必要的 JavaScript(包括 import 语句)移至 “代码围栏” (---).js 文件中。注意:JavaScript 到 有条件地渲染内容 通常直接在 Astro 中编写在 HTML 模板内。

  4. 使用 Astro.props 访问之前传递给 Gatsby 函数的任何其他 props。

  5. 确定是否有任何导入组件也需要转换为 Astro。安装官方 React 集成后,你可以 使用 Astro 文件中现有的 React 组件。但是,你可能希望将它们转换为 .astro 组件,尤其是当它们不需要交互时!

  6. 删除任何 GraphQL 查询。相反,使用 import 和 Astro.glob() 语句来查询本地文件。

Gatsby 博客入门模板的示例逐步转换

¥See an example from Gatsby’s Blog starter template converted step-by-step

¥Compare: .jsx vs .astro

比较以下 Gatsby 组件和相应的 Astro 组件:

¥Compare the following Gatsby component and a corresponding Astro component:

component.jsx
import * as React from "react"
import { useStaticQuery, graphql } from "gatsby"
import Header from "./header"
import Footer from "./footer"
import "./layout.css"
const Component = ({ message, children }) => {
const data = useStaticQuery(graphql`
query SiteTitleQuery {
site {
siteMetadata {
title
}
}
}
`)
return (
<>
<Header siteTitle={data.site.siteMetadata.title} />
<div style={{ margin: `0`, maxWidth: `960`}}>{message}</div>
<main>{children}</main>
<Footer siteTitle={data.site.siteMetadata} />
</>
)
}
export default Component

¥Migrating Layout Files

你可能会发现从将 Gatsby 布局和模板转换为 Astro 布局组件 开始很有帮助。

¥You may find it helpful to start by converting your Gatsby layouts and templates into Astro layout components.

每个 Astro 页面都明确要求存在 <html><head><body> 标签,因此跨页面重用布局文件是很常见的。Astro 对页面内容使用 <slot /> 而不是 React 的 {children} 属性,不需要 import 语句。你的 Gatsby layout.js 和模板将不包含这些。

¥Each Astro page explicitly requires <html>, <head>, and <body> tags to be present, so it is common to reuse a layout file across pages. Astro uses a <slot /> instead of React’s {children} prop for page content, with no import statement required. Your Gatsby layout.js and templates will not include these.

注意标准的 HTML 模板,并直接访问 <head>

¥Note the standard HTML templating, and direct access to <head>:

src/layouts/Layout.astro
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="viewport" content="width=device-width" />
<title>Astro</title>
</head>
<body>
<!-- Wrap the slot element with your existing layout templating -->
<slot />
</body>
</html>

你可能还希望重用 Gatsby’s src/components/seo.js 中的代码以包含其他站点元数据。请注意,Astro 既不使用 <Helmet> 也不使用 <Header>,而是直接创建 <head>。即使在 <head> 内,你也可以导入和使用组件来分离和组织你的页面内容。

¥You may also wish to reuse code from Gatsby’s src/components/seo.js to include additional site metadata. Notice that Astro uses neither <Helmet> nor <Header> but instead creates <head> directly. You may import and use components, even within <head>, to separate and organize your page content.

¥Migrating Pages and Posts

在 Gatsby 中,你的 页面和帖子 可能存在于 src/pages/ 中或 src 之外的另一个文件夹中,例如 content。在 Astro 中,你所有的页面内容都必须位于 src/ 中。

¥In Gatsby, your pages and posts may exist in src/pages/ or outside of src in another folder, like content. In Astro, all your page content must live within src/.

¥React Pages

你现有的 Gatsby JSX (.js) 页面需要是 从 JSX 文件转换为 .astro 页面。你不能在 Astro 中使用现有的 JSX 页面文件。

¥Your existing Gatsby JSX (.js) pages will need to be converted from JSX files to .astro pages. You cannot use an existing JSX page file in Astro.

这些 .astro 必须位于 src/pages/ 内,并且将根据其文件路径自动生成页面路由。

¥These .astro pages must be located within src/pages/ and will have page routes generated automatically based on their file path.

¥Markdown and MDX pages

Astro 内置对 Markdown 的支持以及对 MDX 文件的可选集成。你现有的 Markdown 和 MDX 文件 可以重复使用,但可能需要对其 frontmatter 进行一些调整,例如添加 Astro 的特殊 layout frontmatter 属性。它们还可以放置在 src/pages/ 内以利用基于文件的自动路由。

¥Astro has built-in support for Markdown and an optional integration for MDX files. Your existing Markdown and MDX files can be reused but may require some adjustments to their frontmatter, such as adding Astro’s special layout frontmatter property. They can also be placed within src/pages/ to take advantage of automatic file-based routing.

或者,你可以在 Astro 中使用 内容集合 来存储和管理你的内容。当属于集合的一部分时,Markdown 和 MDX 文件将位于 src/content/ 内的文件夹中。你将自己和 动态生成这些页面 检索内容。

¥Alternatively, you can use content collections in Astro to store and manage your content. When part of a collection, Markdown and MDX files will live in folders within src/content/. You will retrieve the content yourself and generate those pages dynamically.

¥Migrating Tests

由于 Astro 输出原始 HTML,因此可以使用构建步骤的输出编写端到端测试。如果你能够匹配旧版 Gatsby 站点的标记,那么之前编写的任何端到端测试都可以开箱即用。可以在 Astro 中导入和使用 Jest 和 React 测试库等测试库来测试你的 React 组件。

¥As Astro outputs raw HTML, it is possible to write end-to-end tests using the output of the build step. Any end-to-end tests written previously might work out-of-the-box if you have been able to match the markup of the older Gatsby site. Testing libraries such as Jest and React Testing Library can be imported and used in Astro to test your React components.

有关更多信息,请参阅 Astro 的 测试指南

¥See Astro’s testing guide for more.

重新调整配置文件的用途

Section titled 重新调整配置文件的用途

¥Repurpose config files

Gatsby 有几个顶层配置文件,其中还包括站点和页面元数据并用于路由。你不会在 Astro 项目中使用任何这些 gatsby-*.js 文件,但在构建 Astro 项目时可能可以重用一些内容:

¥Gatsby has several top-level configuration files that also include site and page metadata and are used for routing. You will not use any of these gatsby-*.js files in your Astro project, but there may be some content that you can reuse as you build your Astro project:

  • gatsby-config.js:将 siteMetadata: {} 移至 src/data/siteMetadata.js(或 siteMetadata.json),以将有关你网站的数据(标题、描述、社交账户等)导入到页面布局中。

  • gatsby-browser.js:考虑将此处使用的任何内容直接添加到 主要布局<head> 标签中。

  • gatsby-node.js:你不需要在 Astro 中创建自己的节点,但查看此文件中的架构可能会帮助你在 Astro 项目中定义类型。

  • gatsby-ssr.js:如果你选择在 Astro 中使用 SSR,那么你将直接在 astro.config.mjs 中选择你选择的 添加并配置 SSR 适配器

参考:转换为 Astro 语法

Section titled 参考:转换为 Astro 语法

¥Reference: Convert to Astro Syntax

以下是你需要将其转换为 Astro 的 Gatsby 特定语法的一些示例。请参阅编写 Astro 组件指南中的更多 Astro 和 JSX 之间的区别 内容。

¥The following are some examples of Gatsby-specific syntax that you will need to convert to Astro. See more differences between Astro and JSX in the guide to writing Astro components.

¥Gatsby Links to Astro

将任何 Gatsby <Link to=""><NavLink> 等组件转换为 HTML <a href=""> 标签。

¥Convert any Gatsby <Link to="">, <NavLink> etc. components to HTML <a href=""> tags.

<Link to="/blog">Blog</Link>
<a href="/blog">Blog</a>

Astro 不使用任何特殊的链接组件,但欢迎你构建自己的 <Link> 组件。然后,你可以像导入任何其他组件一样导入并使用该 <Link>

¥Astro does not use any special component for links, although you are welcome to build your own <Link> component. You can then import and use this <Link> just as you would any other component.

src/components/Link.astro
---
const { to } = Astro.props
---
<a href={to}><slot /></a>

¥Gatsby Imports to Astro

如有必要,更新任何 file imports 以准确引用相对文件路径。这可以使用 import aliases 或通过完整写出相对路径来完成。

¥If necessary, update any file imports to reference relative file paths exactly. This can be done using import aliases, or by writing out a relative path in full.

请注意,.astro 和其他几种文件类型必须以其完整文件扩展名导入。

¥Note that .astro and several other file types must be imported with their full file extension.

src/pages/authors/Fred.astro
---
import Card from `../../components/Card.astro`;
---
<Card />

Gatsby 子级向 Astro 提供属性

Section titled Gatsby 子级向 Astro 提供属性

¥Gatsby Children Props to Astro

{children} 的任何实例转换为 Astro <slot />。Astro 不需要接收 {children} 作为函数 prop,并且会自动渲染 <slot /> 中的子内容。

¥Convert any instances of {children} to an Astro <slot />. Astro does not need to receive {children} as a function prop and will automatically render child content in a <slot />.

src/components/MyComponent
---
---
export default function MyComponent(props) {
return (
<div>
{props.children}
</div>
);
}
<div>
<slot />
</div>

传递多组子级的 React 组件可以使用 命名槽 迁移到 Astro 组件。

¥React components that pass multiple sets of children can be migrated to an Astro component using named slots.

查看更多有关 Astro 中 <slot /> 的具体用法 的信息。

¥See more about specific <slot /> usage in Astro.

¥Gatsby Styling to Astro

你可能需要将任何 CSS-in-JS 库(例如样式组件)替换为 Astro 中其他可用的 CSS 选项。

¥You may need to replace any CSS-in-JS libraries (e.g. styled-components) with other available CSS options in Astro.

如有必要,将任何内联样式对象 (style={{ fontWeight: "bold" }}) 转换为内联 HTML 样式属性 (style="font-weight:bold;")。或者,使用 Astro <style> 标签 作为作用域 CSS 样式。

¥If necessary, convert any inline style objects (style={{ fontWeight: "bold" }}) to inline HTML style attributes (style="font-weight:bold;"). Or, use an Astro <style> tag for scoped CSS styles.

src/components/Card.astro
<div style={{backgroundColor: `#f4f4f4`, padding: `1em`}}>{message}</div>
<div style="background-color: #f4f4f4; padding: 1em;">{message}</div>

安装 Tailwind 整合 后支持 Tailwind。无需更改你现有的 Tailwind 代码!

¥Tailwind is supported after installing the Tailwind integration. No changes to your existing Tailwind code are required!

全局样式是在 Gatsby 中使用 gatsby-browser.js 中的 CSS 导入来实现的。在 Astro 中,你将直接将 .css 文件导入到主布局组件中以实现全局样式。

¥Global styling is achieved in Gatsby using CSS imports in gatsby-browser.js. In Astro, you will import .css files directly into a main layout component to achieve global styles.

查看更多有关 Astro 样式 的信息。

¥See more about Styling in Astro.

¥Gatsby Image Plugin to Astro

根据你的 React 组件中的情况,将 Gatsby 的 <StaticImage /><GatsbyImage /> 组件转换为 Astro 自有图片集成组件标准 HTML <img> / JSX <img /> 标签。

¥Convert Gatsby’s <StaticImage /> and <GatsbyImage /> components to Astro’s own image integration components, or to a standard HTML <img> / JSX <img /> tag as appropriate in your React components.

src/pages/index.astro
---
import { Image } from 'astro:assets';
import rocket from '../assets/rocket.png';
---
<Image src={rocket} alt="A rocketship in space." />
<img src={rocket.src} alt="A rocketship in space.">

Astro 的 <Image /> 组件仅适用于 .astro.mdx 文件。查看 其组件属性的完整列表 并注意其中几个与 Gatsby 的属性不同。

¥Astro’s <Image /> component works in .astro and .mdx files only. See a full list of its component attributes and note that several will differ from Gatsby’s attributes.

要继续使用标准 Markdown 语法 (![]()) 来使用 Markdown (.md) 文件中的图片,你可能需要更新链接。在 .md 文件中不支持直接使用 HTML <img> 标签来处理本地图片,必须将其转换为 Markdown 语法。

¥To continue using images in Markdown (.md) files using standard Markdown syntax (![]()), you may need to update the link. Using the HTML <img> tag directly is not supported in .md files for local images, and must be converted to Markdown syntax.

src/pages/post-1.md
# My Markdown Page
<!-- Local image stored at src/assets/stars.png -->
![A starry night sky.](../assets/stars.png)

在 React (.jsx) 组件中,使用标准 JSX 图片语法 (<img />)。Astro 不会优化这些映像,但你可以安装和使用 NPM 包以获得更大的灵活性。

¥In React (.jsx) components, use standard JSX image syntax (<img />). Astro will not optimize these images, but you can install and use NPM packages for more flexibility.

你可以在图片指南中了解有关 在 Astro 中使用图片 的更多信息。

¥You can learn more about using images in Astro in the Images Guide.

¥Gatsby GraphQL to Astro

删除对 GraphQL 查询的所有引用,并使用 Astro.glob() 来访问本地文件中的数据。

¥Remove all references to GraphQL queries, and instead use Astro.glob() to access data from your local files.

或者,如果使用内容集合,请使用 getEntry()getCollection() 查询 src/content/ 中的 Markdown 和 MDX 文件。

¥Or, if using content collections, query your Markdown and MDX files in src/content/ using getEntry() and getCollection().

这些数据请求是使用数据在 Astro 组件的 frontmatter 中发出的。

¥These data requests are made in the frontmatter of the Astro component using the data.

src/pages/index.astro
---
import { graphql } from "gatsby"
import { getCollection } from 'astro:content';
// Get all `src/content/blog/` entries
const allBlogPosts = await getCollection('blog');
// Get all `src/pages/posts/` entries
const allPosts = await Astro.glob('../pages/posts/*.md');
---
export const pageQuery = graphql`
{
allMarkdownRemark(sort: { frontmatter: { date: DESC } }) {
nodes {
excerpt
fields {
slug
}
frontmatter {
date(formatString: "MMMM DD, YYYY")
title
description
}
}
}
}
`

指导示例:Gatsby 布局到 Astro

Section titled 指导示例:Gatsby 布局到 Astro

¥Guided example: Gatsby layout to Astro

此示例将 Gatsby 博客启动器的主项目布局 (layout.js) 转换为 src/layouts/Layout.astro

¥This example converts the main project layout (layout.js) from Gatsby’s blog starter to src/layouts/Layout.astro.

此页面布局在访问主页时显示一个标题,并在所有其他页面显示一个带有返回主页链接的不同标题。

¥This page layout shows one header when visiting the home page, and a different header with a link back to Home for all other pages.

  1. Identify the return() JSX.

    layout.js
    import * as React from "react"
    import { Link } from "gatsby"
    const Layout = ({ location, title, children }) => {
    const rootPath = `${__PATH_PREFIX__}/`
    const isRootPath = location.pathname === rootPath
    let header
    if (isRootPath) {
    header = (
    <h1 className="main-heading">
    <Link to="/">{title}</Link>
    </h1>
    )
    } else {
    header = (
    <Link className="header-link-home" to="/">
    Home
    </Link>
    )
    }
    return (
    <div className="global-wrapper" data-is-root-path={isRootPath}>
    <header className="global-header">{header}</header>
    <main>{children}</main>
    <footer>
    © {new Date().getFullYear()}, Built with
    {` `}
    <a href="https://www.gatsbyjs.com">Gatsby</a>
    </footer>
    </div>
    )
    }
    export default Layout
  2. Create Layout.astro and add this return value, converted to Astro syntax.

    Note that:

    • {new Date().getFullYear()} just works 🎉
    • {children} becomes <slot /> 🦥
    • className becomes class 📛
    • Gatsby becomes Astro 🚀
    src/layouts/Layout.astro
    ---
    ---
    <div class="global-wrapper" data-is-root-path={isRootPath}>
    <header class="global-header">{header}</header>
    <main><slot /></main>
    <footer>
    © {new Date().getFullYear()}, Built with
    {` `}
    <a href="https://www.astro.build">Astro</a>
    </footer>
    </div>
  3. Add a page shell so that your layout provides each page with the necessary parts of an HTML document:

    src/layouts/Layout.astro
    ---
    ---
    <html>
    <head>
    <meta charset="utf-8" />
    <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
    <meta name="viewport" content="width=device-width" />
    <title>Astro</title>
    </head>
    <body>
    <div class="global-wrapper" data-is-root-path={isRootPath}>
    <header class="global-header">{header}</header>
    <main>
    <slot />
    </main>
    <footer>
    &#169; {new Date().getFullYear()}, Built with
    {` `}
    <a href="https://www.astro.build">Astro</a>
    </footer>
    </div>
    </body>
    </html>
  4. Add any needed imports, props, and JavaScript

    To conditionally render a header based on the page route and title in Astro:

    • Provide the props via Astro.props. (Remember: your Astro templating accesses props from its frontmatter, not passed into a function.)
    • Use a ternary operator to show one heading if this is the home page, and a different heading otherwise.
    • Remove variables for {header} and {isRootPath} as they are no longer needed.
    • Replace Gatsby’s <Link/> tags with <a> anchor tags.
    • Use class instead of className.
    • Import a local stylesheet from your project for the class names to take effect.
    src/layouts/Layout.astro
    ---
    import '../styles/style.css';
    const { title, pathname } = Astro.props
    ---
    <html>
    <head>
    <meta charset="utf-8" />
    <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
    <meta name="viewport" content="width=device-width" />
    <title>Astro</title>
    </head>
    <body>
    <div class="global-wrapper">
    <header class="global-header">
    { pathname === "/"
    ?
    <h1 class="main-heading">
    <a href="/">{title}</a>
    </h1>
    :
    <h1 class="main-heading">
    <a class="header-link-home" href="/">Home</a>
    </h1>
    }
    </header>
    <main>
    <slot />
    </main>
    <footer>
    &#169; {new Date().getFullYear()}, Built with
    {` `}
    <a href="https://www.astro.build">Astro</a>
    </footer>
    </div>
    </body>
    </html>
  5. Update index.astro to use this new layout and pass it the necessary title and pathname props:

    src/pages/index.astro
    ---
    import Layout from '../layouts/Layout.astro';
    const pagePathname = Astro.url.pathname
    ---
    <Layout title="Home Page" pathname={pagePathname}>
    <p>Astro</p>
    </Layout>
  6. To test the conditional header, create a second page, about.astro using the same pattern:

    src/pages/about.astro
    ---
    import Layout from '../layouts/Layout.astro';
    const pagePathname = Astro.url.pathname
    ---
    <Layout title="About" pathname={pagePathname}>
    <p>About</p>
    </Layout>

    You should see a link to “Home” only when visiting the About page.

¥Community Resources

More migration guides

Astro 中文网 - 粤ICP备13048890号