title | description | type | stub | framework | i18nReady |
---|---|---|---|---|---|
从 Gatsby 迁移 |
将现有的 Gatsby 项目迁移到 Astro 的技巧 |
migration |
false |
Gatsby |
true |
import { Steps } from '@astrojs/starlight/components';
import AstroJSXTabs from '/components/tabs/AstroJSXTabs.astro';
import PackageManagerTabs from '/components/tabs/PackageManagerTabs.astro';
以下是一些关键概念和迁移策略,帮助你开始。使用我们的其他文档和我们的 Discord 社区 继续进行!
Gatsby 和 Astro 共享一些相似性,这将帮助你迁移你的项目:
-
.astro
文件的语法类似于 JSX。编写 Astro 应该感觉熟悉。 -
Astro 内置对 Markdown 的支持,并且有一个使用 MDX 文件的集成。此外,你可以配置并继续使用许多现有的 Markdown 插件。
-
Astro 还有一个使用 React 组件的官方集成。注意,在 Astro 中,React 文件必须有
.jsx
或.tsx
扩展名。 -
Astro 支持安装 NPM 包,包括 React 库。你的许多现有依赖项将在 Astro 中工作。
-
像 Gatsby 一样,Astro 项目可以是 SSG 或者服务端渲染 (SSR) 与页面级预渲染。
当你在 Astro 中重建你的 Gatsby 站点时,你会注意到一些重要的差异:
-
Gatsby 项目是 React 单页应用,并使用
index.js
作为你的项目的根。Astro 项目是多页站点,index.astro
是你的主页。 -
Astro 组件不是以返回页面模板的出口函数形式编写的。相反,你将你的代码分割为专门为你的 JavaScript 设计的 "代码围栏" 和专门为你生成的 HTML 设计的主体。
-
本地文件数据:Gatsby 使用 GraphQL 从你的项目文件中检索数据。Astro 使用 ESM imports 和顶层 await 函数(例如
Astro.glob()
,getCollection()
)从你的项目文件中导入数据。你可以手动向你的 Astro 项目添加 GraphQL,但默认情况下不包含它。
每个项目迁移都会有所不同,但是在将 Gatsby 转换为 Astro 时,你将执行一些常见操作。
使用你的包管理器的 create astro
命令启动 Astro 的 CLI 向导,或从 Astro 主题展示中选择一个社区主题。
你可以向 create astro
命令传递一个 --template
参数,以使用我们的官方起始器(例如 docs
,blog
,portfolio
)启动一个新的 Astro 项目。或者,你可以从 GitHub 上的任何现有 Astro 存储库开始一个新项目。
# 使用官方示例创建一个新项目
npm create astro@latest -- --template <example-name>
```
</Fragment>
<Fragment slot="pnpm">
```shell
# 启动 Astro CLI 向导
pnpm create astro@latest
# 使用官方示例创建一个新项目
pnpm create astro@latest --template <example-name>
```
</Fragment>
<Fragment slot="yarn">
```shell
# 启动 Astro CLI 向导
yarn create astro@latest
# 使用官方示例创建一个新项目
yarn create astro@latest --template <example-name>
```
</Fragment>
然后,将你现有的 Gatsby 项目文件复制到你的新 Astro 项目中,放在 src
外面的单独文件夹中。
:::tip 访问 https://astro.new 查看完整的官方起始模板列表,以及在 StackBlitz、CodeSandbox 或 Gitpod 中打开新项目的链接。 :::
在将你的 Gatsby 项目转换为 Astro 时,你可能会发现安装一些Astro 的可选集成很有用:
-
@astrojs/react:在你的新 Astro 站点中重用一些现有的 React UI 组件,或者继续使用 React 组件。
-
@astrojs/mdx:从你的 Gatsby 项目中带来现有的 MDX 文件,或者在你的新 Astro 站点中使用 MDX。
按照 Astro 的项目结构:
1. **删除** Gatsby 的 `public/` 文件夹。Gatsby 使用 `public/` 目录作为其构建输出,所以你可以安全地丢弃这个文件夹。你将不再需要你的 Gatsby 站点的构建版本。(Astro 默认使用 `dist/` 作为构建输出。)
-
重命名 Gatsby 的
static/
文件夹为public/
,并将其用作 Astro 的public/
文件夹。Astro 使用一个叫做
public/
的文件夹来存放静态资源。你也可以将static/
的内容复制到你现有的 Astropublic/
文件夹中。 -
复制或移动 Gatsby 的其他文件和文件夹(例如
components
,pages
等)根据需要将其复制或移动到你的 Astrosrc/
文件夹中,重建你的站点,按照 Astro 的项目结构。Astro 的
src/pages/
文件夹是一个特殊文件夹,用于基于文件的路由,从.astro
、.md
和.mdx
文件中创建你的站点的页面和文章。你不必为你的 Astro、Markdown 和 MDX 文件配置任何路由行为。所有其他文件夹都是可选的,你可以按照你喜欢的方式组织你的
src/
文件夹的内容。Astro 项目中的其他常见文件夹包括src/layouts/
、src/components
、src/styles
和src/scripts
。
以下是将 Gatsby .js
组件转换为 .astro
组件的一些提示:
-
将现有的 Gatsby 组件函数的
return()
部分作为你的 HTML 模板。 -
将任何 Gatsby 或 JSX 语法转换为 Astro 语法或 HTML web 标准。例如
<Link to="">
,{children}
和className
。 -
将所有必要的 JavaScript,包括 import 语句,都放入"代码围栏" (
---
)中。注意:在 Astro 中,经常会直接在 HTML 模板内编写条件渲染内容的 JavaScript。 -
使用
Astro.props
来访问之前传递给你的 Gatsby 函数的任何其他 props。 -
决定是否需要将导入的组件也转换为 Astro。如果已经安装了官方的 React 集成,你可以在 Astro 文件中使用现有的 React 组件。但是,如果他们不需要交互,你可能希望将它们转换为
.astro
组件! -
删除任何 GraphQL 查询。改为使用 import 和
Astro.glob()
语句来查询你的本地文件。
比较以下的 Gatsby 组件与相应的 Astro 组件:
```jsx title="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
```
首先,你可能会发现将你的 Gatsby 布局和模板转换为 Astro 布局组件会很有帮助。
每个 Astro 页面明确要求 <html>
、<head>
和 <body>
标签的存在,所以在页面之间复用布局文件是常见的做法。Astro 使用 <slot />
而不是 React 的 {children}
prop 来放置页面内容,并且无需导入语句。你的 Gatsby layout.js
和模板将不会包含这些。
注意标准 HTML 模板以及对 <head>
的直接访问:
<html lang="zh">
<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>
<!-- 将 slot 元素包裹在你现有的布局模板中 -->
<slot />
</body>
</html>
你可能还希望从 Gatsby 的 src/components/seo.js
中复用代码,以便包含额外的站点元数据。注意 Astro 并不使用 <Helmet>
或 <Header>
,而是直接创建 <head>
。你可以导入和使用组件,甚至在 <head>
中也可以,以分离和组织你的页面内容。
在 Gatsby 中,你的页面和文章可能存在于 src/pages/
或者在 src
外部的其他文件夹,如 content
。而在 Astro 中,所有的页面内容必须位于 src/
内。
你现有的 Gatsby JSX(.js
)页面需要被从 JSX 文件转换为 .astro
页面。你不能在 Astro 中使用现有的 JSX 页面文件。
这些.astro
页面 必须位于 src/pages/
内,并且会基于它们的文件路径自动生成页面路由。
Astro 对 Markdown 有内置支持,并对 MDX 文件有可选集成。你现有的 Markdown 和 MDX 文件 可以重用,但可能需要对它们的 frontmatter 进行一些调整,如添加 Astro 的特殊 layout
frontmatter 属性。它们也可以被放置在 src/pages/
中以利用自动的基于文件的路由。
或者,你还可以使用 Astro 中的 内容集合 来存储和管理你的内容。作为集合的一部分时,Markdown 和 MDX 文件将位于 src/content/
内的文件夹中。你将需要自己获取内容并动态生成这些页面。
由于 Astro 输出原始 HTML,因此可以使用构建步骤的输出编写端到端测试。如果你能匹配旧的 Gatsby 站点的标记,以前编写的任何端到端测试可能都可以开箱即用。测试库如 Jest 和 React Testing Library 可以在 Astro 中导入和使用,以测试你的 React 组件。
查看 Astro 的 测试指南 了解更多。
Gatsby 有几个顶级配置文件,也包括站点和页面元数据,并用于路由。在你的 Astro 项目中,你不会使用任何这些 gatsby-*.js
文件,但可能有一些内容可以在构建 Astro 项目时重用:
-
gatsby-config.js
:将你的siteMetadata: {}
移动到src/data/siteMetadata.js
(或siteMetadata.json
)中,以便在页面布局中导入关于你的站点(标题,描述,社交账号等)的数据。 -
gatsby-browser.js
:考虑将这里使用的任何东西直接添加到你的主布局的<head>
标签中。 -
gatsby-node.js
:在 Astro 中你不需要创建你自己的节点,但查看该文件中的 schema 可能有助于你在 Astro 项目中定义类型。 -
gatsby-ssr.js
:如果你选择在 Astro 中使用 SSR,你将在astro.config.mjs
中添加和配置你选择的 SSR 适配器。
以下是一些你需要将其转换为 Astro 的 Gatsby 特有语法的示例。在编写 Astro 组件的指南中查看更多 Astro 和 JSX 之间的区别。
将任何 Gatsby 的 <Link to="">
、<NavLink>
等组件转换为 HTML 的 <a href="">
标签。
<Link to="/blog">博客</Link>
<a href="/blog">博客</a>
Astro 不使用任何特殊的链接组件,尽管你可以创建你自己的 <Link>
组件。然后你可以像使用任何其他组件一样导入和使用这个 <Link>
。
---
const { to } = Astro.props
---
<a href={to}><slot /></a>
如有必要,更新任何文件导入以准确引用相对文件路径。这可以通过使用导入别名,或者完全写出相对路径来完成。
请注意,.astro
和若干其他文件类型必须使用完整的文件扩展名进行导入。
---
import Card from `../../components/Card.astro`;
---
<Card />
将任何 {children}
实例转换为 Astro 的 <slot />
。Astro 不需要将 {children}
作为函数 prop 接收,并且会自动在 <slot />
中渲染子内容。
---
---
export default function MyComponent(props) {
return (
<div>
{props.children}
</div>
);
}
<div>
<slot />
</div>
传递多个子集的 React 组件可以通过使用 命名插槽 迁移到 Astro 组件。
在 Astro 中查看更多关于特定 <slot />
使用的信息.
你可能需要用 Astro 中其他可用的 CSS 选项替换任何 CSS-in-JS 库(例如 styled-components)。
如果需要,将内联样式对象(style={{ fontWeight: "bold" }}
)转换为内联 HTML 样式属性(style="font-weight:bold;"
)。或者,使用 Astro <style>
标签 进行作用域 CSS 样式。
<div style={{backgroundColor: `#f4f4f4`, padding: `1em`}}>{message}</div>
<div style="background-color: #f4f4f4; padding: 1em;">{message}</div>
在安装了 Tailwind 集成 后支持 Tailwind。不需要对现有的 Tailwind 代码进行任何更改!
Gatsby 中使用 gatsby-browser.js
中的 CSS 导入实现全局样式。在 Astro 中,你将直接导入 .css
文件到主布局组件中以实现全局样式。
查看关于 Astro 中的样式 的更多信息。
根据情况在你的 React 组件中将 Gatsby 的 <StaticImage />
和 <GatsbyImage />
组件转换为 Astro 自己的图像集成组件 或者转化成 标准的 HTML <img>
/ JSX <img />
标签。
---
import { Image } from 'astro:assets';
import rocket from '../assets/rocket.png';
---
<Image src={rocket} alt="太空中的火箭飞船。" />
<img src={rocket.src} alt="太空中的火箭飞船。">
Astro 的 <Image />
组件只能在 .astro
和 .mdx
文件中工作。查看该组件可用的完整组件属性列表,并注意它与 Gatsby 的属性有一些不同。
要继续使用标准 Markdown 语法 (![]()
) 在 Markdown (.md
) 文件中使用图像,你可能需要更新链接。对于本地图像,不支持在 .md
文件中直接使用 HTML <img>
标签,必须转换为 Markdown 语法。
<!-- src/pages/post-1.md -->
# 我的 Markdown 页面
<!-- 存储在 src/assets/stars.png 的本地图片 -->
![A starry night sky.](../assets/stars.png)
在 React(.jsx
)组件中,使用标准的 JSX 图像语法(<img />
)。Astro 不会优化这些图像,但你可以安装和使用 NPM 包以获得更大的灵活性。
你可以在图像指南中了解更多关于 在 Astro 中使用图像 的信息。
删除所有引用 GraphQL 查询的地方,然后使用 Astro.glob()
来访问你的本地文件中的数据。
或者,如果使用内容集合,使用 getEntry()
和 getCollection()
在 src/content/
中查询你的 Markdown 和 MDX 文件。
这些数据请求是在 Astro 组件的 frontmatter 中使用数据进行的。
---
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
}
}
}
}
`
此示例将主项目布局(layout.js
)从 Gatsby 的博客起始器转换为 src/layouts/Layout.astro
。
当访问首页时,此页面布局显示一个标题,而在访问所有其他页面时,显示带有返回首页链接的另一个标题。
1. 确定 `return()` JSX。```jsx {21-29} title="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
```
-
创建
Layout.astro
并添加此return
值,转换为 Astro 语法。请注意:
{new Date().getFullYear()}
无需改动 🎉{children}
变为<slot />
🦥className
变为class
📛Gatsby
变为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>
-
添加一个页面框架,使你的布局为每个页面提供 HTML 文档所需的内容:
--- --- <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> © {new Date().getFullYear()}, Built with {` `} <a href="https://www.astro.build">Astro</a> </footer> </div> </body> </html>
-
添加所需的导入、props 和 JavaScript
根据 Astro 中页面路由和标题条件性地渲染 header:
- 通过
Astro.props
提供 props。(记住:你的 Astro 模板从它的 frontmatter 中访问 props,而不是传入到一个函数中。) - 如果这是主页,使用三元运算符显示一个标题,否则显示另一个标题。
- 删除
{header}
和{isRootPath}
变量,因为它们不再需要。 - 将 Gatsby 的
<Link/>
标签替换为<a>
锚标签。 - 使用
class
替代className
。 - 从项目中导入一个本地样式表,使类名称生效。
--- 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> © {new Date().getFullYear()}, Built with {` `} <a href="https://www.astro.build">Astro</a> </footer> </div> </body> </html>
- 通过
-
更新
index.astro
来使用这个新的布局,并传递必需的title
和pathname
props:--- import Layout from '../layouts/Layout.astro'; const pagePathname = Astro.url.pathname --- <Layout title="主页" pathname={pagePathname}> <p>Astro</p> </Layout>
:::tip 你可以使用
Astro.url
获取当前页面的路径。 ::: -
为了测试条件 header,使用相同的模式创建第二个页面
about.astro
:--- import Layout from '../layouts/Layout.astro'; const pagePathname = Astro.url.pathname --- <Layout title="关于" pathname={pagePathname}> <p>关于</p> </Layout>
当你访问关于页面时,你应该只看到指向 "主页" 的链接。
-
博客帖子:从 Gatsby 迁移到 Astro
-
博客帖子:迁移到 Astro 是多么的简单。
-
博客帖子:我为什么从 Gatsby 切换到 Astro。
-
博客帖子:我为什么从 Gatsby 迁移到 Astro。
-
博客帖子:再次迁移:从 Gatsby 到 Astro。
:::note[你有资源分享吗?] 如果你找到(或制作)了一个关于将 Gatsby 网站转换为 Astro 的有用的视频或博客文章,编辑此页面并将其添加到这里! :::