从 Gatsby 迁移
这里有一些关键概念和迁移策略可以帮助你入门。利用我们文档的其余部分和我们的 Discord 社区 继续前进!
Gatsby 和 Astro 之间的主要相似之处
“Gatsby 和 Astro 之间的主要相似之处”部分Gatsby 和 Astro 有一些相似之处,这将帮助你迁移项目
-
.astro
文件的语法与 JSX 类似。编写 Astro 应该会感到熟悉。 -
Astro 内置支持 Markdown,并集成了 MDX 文件。此外,你可以配置并继续使用许多现有的 Markdown 插件。
-
Astro 还提供了使用 React 组件的官方集成。请注意,在 Astro 中,React 文件**必须**具有
.jsx
或.tsx
扩展名。 -
Astro 支持安装 NPM 包,包括 React 库。你现有的许多依赖项都可以在 Astro 中工作。
-
与 Gatsby 类似,Astro 项目可以是 SSG 或 带页面级预渲染的 SSR。
Gatsby 和 Astro 之间的主要区别
“Gatsby 和 Astro 之间的主要区别”部分当你用 Astro 重建 Gatsby 站点时,你会注意到一些重要的区别
-
Gatsby 项目是 React 单页应用程序,并使用
index.js
作为项目的根。Astro 项目是多页站点,index.astro
是你的主页。 -
Astro 组件不是编写为返回页面模板的导出函数。相反,你会将代码拆分为 JavaScript 的“代码围栏”和专门用于生成 HTML 的主体。
-
本地文件数据:Gatsby 使用 GraphQL 从项目文件中检索数据。Astro 使用 ESM 导入和顶级 await 函数(例如
import.meta.glob()
、getCollection()
)从项目文件中导入数据。你可以在 Astro 项目中手动添加 GraphQL,但它默认不包含在内。
转换你的 Gatsby 项目
“转换你的 Gatsby 项目”部分每个项目迁移都会有所不同,但从 Gatsby 转换到 Astro 时,你会执行一些常见操作。
创建一个新的 Astro 项目
“创建一个新的 Astro 项目”部分使用你的包管理器的 create astro
命令来启动 Astro 的 CLI 向导,或从 Astro 主题展示中选择一个社区主题。
你可以将 --template
参数传递给 create astro
命令,以使用我们的官方启动器(例如 docs
、blog
、portfolio
)启动一个新的 Astro 项目。或者,你可以从 GitHub 上的任何现有 Astro 仓库启动新项目。
# launch the Astro CLI Wizardnpm create astro@latest
# create a new project with an official examplenpm create astro@latest -- --template <example-name>
# launch the Astro CLI Wizardpnpm create astro@latest
# create a new project with an official examplepnpm create astro@latest --template <example-name>
# launch the Astro CLI Wizardyarn create astro@latest
# create a new project with an official exampleyarn create astro@latest --template <example-name>
然后,将现有的 Gatsby 项目文件复制到你的新 Astro 项目中,放入 src
之外的独立文件夹中。
访问 https://astro.new 查看官方入门模板的完整列表,以及在 IDX、StackBlitz、CodeSandbox 或 Gitpod 中打开新项目的链接。
安装集成(可选)
“安装集成(可选)”部分在将 Gatsby 项目转换为 Astro 时,你会发现安装一些 Astro 的可选集成很有用
-
@astrojs/react:在新 Astro 站点中重用现有 React UI 组件或继续使用 React 组件。
-
@astrojs/mdx:从你的 Gatsby 项目中引入现有 MDX 文件,或在新 Astro 站点中使用 MDX。
将你的代码放入 src
“将你的代码放入 src”部分遵循 Astro 的项目结构
-
删除 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
。
提示:将 JSX 文件转换为 .astro
文件
“提示:将 JSX 文件转换为 .astro 文件”部分以下是将 Gatsby .js
组件转换为 .astro
组件的一些提示
-
只使用现有 Gatsby 组件函数的
return()
作为你的 HTML 模板。 -
将任何 Gatsby 或 JSX 语法更改为 Astro 语法或 HTML Web 标准。例如,这包括
<Link to="">
、{children}
和className
。 -
将所有必要的 JavaScript(包括导入语句)移动到“代码围栏”(
---
)中。注意:在 Astro 中,用于条件渲染内容的 JavaScript 通常直接写在 HTML 模板内。 -
使用
Astro.props
访问之前传递给 Gatsby 函数的任何附加 props。 -
决定是否需要将任何导入的组件也转换为 Astro。安装了官方 React 集成后,你可以在 Astro 文件中使用现有 React 组件。但是,你可能希望将它们转换为
.astro
组件,特别是如果它们不需要交互的话! -
删除任何 GraphQL 查询。改为使用 import 和
import.meta.glob()
语句来查询本地文件。
参阅Gatsby 博客启动模板转换为 Astro 的逐步示例
比较:.jsx
与 .astro
“比较:.jsx 与 .astro”部分比较以下 Gatsby 组件和相应的 Astro 组件
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
---import Header from "./Header.astro"import Footer from "./Footer.astro"import "../styles/stylesheet.css"import { site } from "../data/siteMetaData.js"const { message } = Astro.props---<Header siteTitle={site.title} /> <div style="margin: 0; max-width: 960;">{message}</div> <main> <slot /> </main><Footer siteTitle={site.title} />
迁移布局文件
“迁移布局文件”部分你可能会发现,首先将 Gatsby 布局和模板转换为Astro 布局组件会很有帮助。
每个 Astro 页面都明确要求存在 <html>
、<head>
和 <body>
标签,因此在页面之间重用布局文件很常见。Astro 使用 <slot />
代替 React 的 {children}
prop 来表示页面内容,不需要导入语句。你的 Gatsby layout.js
和模板将不包含这些。
注意标准的 HTML 模板和对 <head>
的直接访问
<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 的 src/components/seo.js
中的代码,以包含额外的站点元数据。请注意,Astro 既不使用 <Helmet>
也不使用 <Header>
,而是直接创建 <head>
。你可以导入和使用组件,即使在 <head>
中,也可以分离和组织页面内容。
迁移页面和文章
“迁移页面和文章”部分在 Gatsby 中,你的页面和文章可能存在于 src/pages/
中,或者位于 src
之外的另一个文件夹中,例如 content
。在 Astro 中,你所有的页面内容都必须位于 src/
中,除非你使用内容集合。
React 页面
“React 页面”部分你现有的 Gatsby JSX (.js
) 页面需要从 JSX 文件转换为 .astro
页面。你不能在 Astro 中使用现有的 JSX 页面文件。
这些 .astro
页面必须位于 src/pages/
内,并且会根据其文件路径自动生成页面路由。
Markdown 和 MDX 页面
“Markdown 和 MDX 页面”部分Astro 内置支持 Markdown,并提供 MDX 文件的可选集成。你现有的Markdown 和 MDX 文件可以重用,但可能需要对它们的 frontmatter 进行一些调整,例如添加Astro 的特殊 layout
frontmatter 属性。它们也可以放置在 src/pages/
中,以利用自动基于文件的路由。
或者,你可以在 Astro 中使用内容集合来存储和管理你的内容。你将自行检索内容并动态生成这些页面。
迁移测试
“迁移测试”部分由于 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 语法
“参考:转换为 Astro 语法”部分以下是一些你需要转换为 Astro 语法的 Gatsby 特有语法的示例。在 Astro 组件编写指南中查看更多Astro 与 JSX 之间的差异。
Gatsby 链接到 Astro
“Gatsby 链接到 Astro”部分将所有 Gatsby <Link to="">
、<NavLink>
等组件转换为 HTML <a href="">
标签。
<Link to="/blog">Blog</Link><a href="/blog">Blog</a>
Astro 不使用任何特殊的链接组件,但你可以构建自己的 <Link>
组件。然后,你可以像使用任何其他组件一样导入和使用此 <Link>
。
---const { to } = Astro.props---<a href={to}><slot /></a>
Gatsby 导入到 Astro
“Gatsby 导入到 Astro”部分如有必要,更新所有文件导入,以精确引用相对文件路径。这可以通过导入别名或完整编写相对路径来完成。
请注意,.astro
和其他几种文件类型必须使用其完整的文件扩展名进行导入。
---import Card from `../../components/Card.astro`;---<Card />
Gatsby Children Props 到 Astro
“Gatsby Children Props 到 Astro”部分将所有 {children}
实例转换为 Astro 的 <slot />
。Astro 不需要将 {children}
作为函数 prop 接收,并且会自动在 <slot />
中渲染子内容。
------export default function MyComponent(props) { return ( <div> {props.children} </div> );}
<div> <slot /></div>
传递多组子组件的 React 组件可以使用命名插槽迁移到 Astro 组件。
查看更多关于Astro 中 <slot />
的具体用法。
Gatsby 样式到 Astro
“Gatsby 样式到 Astro”部分你可能需要将任何 CSS-in-JS 库(例如 styled-components)替换为 Astro 中其他可用的 CSS 选项。
如有必要,将所有内联样式对象(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 Vite 插件后即可支持 Tailwind。无需对你现有的 Tailwind 代码进行任何更改!
Gatsby 中通过在 gatsby-browser.js
中导入 CSS 来实现全局样式。在 Astro 中,你将直接将 .css
文件导入到主布局组件中以实现全局样式。
查看更多关于在 Astro 中设置样式的信息。
Gatsby 图像插件到 Astro
“Gatsby 图像插件到 Astro”部分将 Gatsby 的 <StaticImage />
和 <GatsbyImage />
组件转换为Astro 自己的图像集成组件,或转换为 React 组件中适当的标准 HTML <img>
/ JSX <img />
标签。
---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 的属性不同。
要继续在 Markdown (.md
) 文件中使用标准 Markdown 语法(![]()
)的图片,你可能需要更新链接。对于本地图片,在 .md
文件中直接使用 HTML <img>
标签不受支持,必须转换为 Markdown 语法。
# My Markdown Page
<!-- Local image stored at src/assets/stars.png -->
在 React (.jsx
) 组件中,使用标准的 JSX 图像语法(<img />
)。Astro 不会优化这些图像,但你可以安装和使用 NPM 包以获得更大的灵活性。
你可以在图像指南中了解更多关于在 Astro 中使用图像的信息。
Gatsby GraphQL 到 Astro
“Gatsby GraphQL 到 Astro”部分删除所有对 GraphQL 查询的引用,改为使用 import.meta.glob()
来访问本地文件中的数据。
或者,如果使用内容集合,请使用 getEntry()
和 getCollection()
查询你的 Markdown 和 MDX 文件。
这些数据请求在 Astro 组件的 frontmatter 中使用数据进行。
---import { graphql } from "gatsby"import { getCollection } from 'astro:content';
// Get all `src/content/blog/` entriesconst allBlogPosts = await getCollection('blog');
// Get all `src/pages/posts/` entriesconst allPosts = Object.values(import.meta.glob('../pages/post/*.md', { eager: true }));---
export const pageQuery = graphql` { allMarkdownRemark(sort: { frontmatter: { date: DESC } }) { nodes { excerpt fields { slug } frontmatter { date(formatString: "MMMM DD, YYYY") title description } } } }`
引导示例:Gatsby 布局到 Astro
“引导示例:Gatsby 布局到 Astro”部分此示例将 Gatsby 博客启动器中的主项目布局(layout.js
)转换为 src/layouts/Layout.astro
。
此页面布局在访问主页时显示一个页头,在访问所有其他页面时显示带有返回主页链接的不同页头。
-
识别
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 === rootPathlet headerif (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
🚀
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> -
添加页面外壳,使你的布局为每个页面提供必要的 HTML 文档部分
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>© {new Date().getFullYear()}, Built with{` `}<a href="https://www.astro.build">Astro</a></footer></div></body></html> -
添加任何所需的导入、props 和 JavaScript
在 Astro 中根据页面路由和标题有条件地渲染页头
- 通过
Astro.props
提供 props。(请记住:你的 Astro 模板从其 frontmatter 访问 props,而不是传递到函数中。) - 使用三元运算符,如果这是主页,则显示一个标题,否则显示另一个标题。
- 移除
{header}
和{isRootPath}
的变量,因为它们不再需要。 - 将 Gatsby 的
<Link/>
标签替换为<a>
锚点标签。 - 使用
class
而不是className
。 - 从你的项目中导入本地样式表,使类名生效。
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>© {new Date().getFullYear()}, Built with{` `}<a href="https://www.astro.build">Astro</a></footer></div></body></html> - 通过
-
更新
index.astro
以使用此新布局,并向其传递必要的title
和pathname
propssrc/pages/index.astro ---import Layout from '../layouts/Layout.astro';const pagePathname = Astro.url.pathname---<Layout title="Home Page" pathname={pagePathname}><p>Astro</p></Layout> -
要测试条件页头,请使用相同的模式创建第二个页面
about.astro
src/pages/about.astro ---import Layout from '../layouts/Layout.astro';const pagePathname = Astro.url.pathname---<Layout title="About" pathname={pagePathname}><p>About</p></Layout>你只在访问“关于”页面时才能看到“主页”链接。
社区资源
“社区资源”部分如果你找到(或制作了!)关于将 Gatsby 站点转换为 Astro 的有用视频或博客文章,请将其添加到此列表!