跳转到内容

从 Create React App (CRA) 迁移

Astro 的 React 集成 支持在 Astro 组件内部使用 React 组件,包括像 Create React App (CRA) 这样的完整 React 应用!

src/pages/index.astro
---
// Import your root App component
import App from '../cra-project/App.jsx';
---
<!-- Use a client directive to load your app -->
<App client:load />
查看如何使用 React Router 用 Astro 构建单页应用 (SPA) 外部链接

当你将许多应用直接添加到已安装 React 集成的 Astro 项目中时,它们会作为完整的 React 应用“开箱即用”。这是让你的项目立即启动并运行,并在迁移到 Astro 的同时保持应用功能的好方法。

随着时间的推移,你可以将你的结构逐步转换为 .astro.jsx 组件的组合。你可能会发现你需要的 React 组件比你想象的要少!

这里有一些关键概念和迁移策略可以帮助你入门。利用我们文档的其余部分和我们的 Discord 社区 继续前进!

当你在 Astro 中重建你的 CRA 网站时,你会注意到一些重要的区别

  • CRA 是一个单页应用,使用 index.js 作为项目的根。Astro 是一个多页网站,index.astro 是你的主页。

  • .astro 组件不是作为返回页面模板的导出函数编写的。相反,你会将代码分割成用于 JavaScript 的“代码栅栏”和一个专门用于生成 HTML 的主体。

  • 内容驱动:Astro 的设计初衷是展示你的内容,并允许你仅在需要时选择性地加入交互性。现有的 CRA 应用可能是为高客户端交互性而构建的,可能需要高级的 Astro 技术来包含使用 .astro 组件更难复制的项目,例如仪表盘。

你现有的应用可以直接在新的 Astro 项目中渲染,通常无需更改应用代码。

使用你的包管理器的 create astro 命令启动 Astro 的 CLI 向导,并选择一个新的“空” Astro 项目。

终端窗口
npm create astro@latest

使用你的包管理器的 astro add 命令添加 React 集成。如果你的应用使用 astro add 命令支持的其他包,如 Tailwind 和 MDX,你可以用一个命令将它们全部添加

终端窗口
npx astro add react
npx astro add react tailwind mdx

如果你的 CRA 需要任何依赖项(例如 NPM 包),则通过命令行单独安装它们,或者将它们手动添加到新 Astro 项目的 package.json 中,然后运行安装命令。请注意,许多(但不是所有)React 依赖项都可以在 Astro 中工作。

将你现有的 Create React App (CRA) 项目源文件和文件夹(例如 componentshooksstyles 等)复制到 src/ 内的一个新文件夹中,保持其文件结构,以便你的应用能继续工作。请注意,所有 .js 文件扩展名都必须重命名为 .jsx.tsx

不要包含任何配置文件。你将使用 Astro 自己的 astro.config.mjspackage.jsontsconfig.json

将你的应用 public/ 文件夹的内容(例如静态资源)移动到 Astro 的 public/ 文件夹中。

  • 目录public/
    • logo.png
    • favicon.ico
  • 目录src/
    • 目录cra-project/
      • App.jsx
    • 目录pages/
      • index.astro
  • astro.config.mjs
  • package.json
  • tsconfig.json

index.astro 的 frontmatter 部分导入你应用的根组件,然后在你的页面模板中渲染 <App /> 组件

src/pages/index.astro
---
import App from '../cra-project/App.jsx';
---
<App client:load />

将你现有的应用添加到 Astro 之后,你可能想将你的应用本身转换为 Astro!

你将复制一个类似的基于组件的设计,使用 Astro HTML 模板组件作为你的基本结构,同时为交互岛导入和包含单个 React 组件(这些组件本身可能就是完整的应用!)。

每次迁移都会有所不同,并且可以增量进行,而不会中断你正在运行的应用。按照自己的节奏转换各个部分,这样随着时间的推移,你的应用将越来越多地由 Astro 组件驱动。

在转换你的 React 应用时,你将决定哪些 React 组件要重写为 Astro 组件。你唯一的限制是 Astro 组件可以导入 React 组件,但 React 组件只能导入其他 React 组件

src/pages/static-components.astro
---
import MyReactComponent from '../components/MyReactComponent.jsx';
---
<html>
<body>
<h1>Use React components directly in Astro!</h1>
<MyReactComponent />
</body>
</html>

你可以将 React 组件嵌套在单个 Astro 组件中,而不是将 Astro 组件导入到 React 组件中

src/pages/nested-components.astro
---
import MyReactSidebar from '../components/MyReactSidebar.jsx';
import MyReactButton from '../components/MyReactButton.jsx';
---
<MyReactSidebar>
<p>Here is a sidebar with some text and a button.</p>
<div slot="actions">
<MyReactButton client:idle />
</div>
</MyReactSidebar>

在将你的 CRA 重构为 Astro 项目之前,了解 Astro 岛Astro 组件可能会对你有所帮助。

比较下面的 CRA 组件和相应的 Astro 组件

StarCount.jsx
import React, { useState, useEffect } from 'react';
import Header from './Header';
import Footer from './Footer';
const Component = () => {
const [stars, setStars] = useState(0);
const [message, setMessage] = useState('');
useEffect(() => {
const fetchData = async () => {
const res = await fetch('https://api.github.com/repos/withastro/astro');
const json = await res.json();
setStars(json.stargazers_count || 0);
setMessage(json.message);
};
fetchData();
}, []);
return (
<>
<Header />
<p style={{
backgroundColor: `#f4f4f4`,
padding: `1em 1.5em`,
textAlign: `center`,
marginBottom: `1em`
}}>Astro has {stars} 🧑‍🚀</p>
<Footer />
</>
)
};
export default Component;

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

  1. 使用现有 CRA 组件函数返回的 JSX 作为你的 HTML 模板的基础。

  2. 将任何 CRA 或 JSX 语法转换为 Astro 或 HTML Web 标准。例如,这包括 {children}className

  3. 将任何必要的 JavaScript(包括导入语句)移动到“代码栅栏”(---)中。注意:用于条件性渲染内容的 JavaScript 通常直接写在 Astro 的 HTML 模板中。

  4. 使用 Astro.props 访问之前传递给你的 CRA 函数的任何附加 props。

  5. 决定是否需要将任何导入的组件也转换为 Astro。你现在或永远都可以将它们保留为 React 组件。但是,你最终可能希望将它们转换为 .astro 组件,特别是如果它们不需要交互的话!

  6. 用导入语句或 import.meta.glob() 替换 useEffect() 来查询本地文件。使用 fetch() 来获取外部数据。

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

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

更新任何文件导入,以精确引用相对文件路径。这可以通过使用导入别名或完整写出相对路径来完成。

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

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

将任何 {children} 的实例转换为 Astro 的 <slot />。Astro 不需要以函数 prop 的形式接收 {children},它会自动在 <slot /> 中渲染子内容。

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

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

查看更多关于Astro 中 <slot /> 的具体用法

在 Create React App 组件中获取数据与在 Astro 中类似,但有一些细微的差别。

你需要移除任何副作用钩子(useEffect)的实例,改用 import.meta.glob()getCollection()/getEntry() 来访问项目源中其他文件的数据。

获取远程数据,请使用 fetch()

这些数据请求在 Astro 组件的 frontmatter 中进行,并使用顶层 await。

src/pages/index.astro
---
import { getCollection } from 'astro:content';
// Get all `src/content/blog/` entries
const allBlogPosts = await getCollection('blog');
// Get all `src/pages/posts/` entries
const allPosts = Object.values(import.meta.glob('../pages/post/*.md', { eager: true }));
// Fetch remote data
const response = await fetch('https://randomuser.me/api/');
const data = await response.json();
const randomUser = data.results[0];
---

查看更多关于使用 import.meta.glob() 导入本地文件、使用 Collections API 查询获取远程数据的信息。

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

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

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

安装 Tailwind Vite 插件后即可支持 Tailwind。无需对你现有的 Tailwind 代码进行任何更改!

查看更多关于在 Astro 中设置样式的信息。

你的 CRA 可能在 Astro 中“开箱即用”!但是,你很可能需要进行一些微调来复制现有应用的功能和/或样式。

如果你在本文档中找不到答案,请访问 Astro Discord 并在我们的支持论坛中提问!

更多迁移指南

贡献 社区 赞助