从 Create React App(CRA)迁移

Astro 的 React 集成 支持在 Astro 组件中使用 React 组件,甚至包括像 Create React App (CRA) 这样的整个 React 应用程序!

src/pages/index.astro
---
// 导入你的根应用组件
import App from '../cra-project/App.jsx'
---
<!-- 使用客户端指令加载你的应用 -->
<App client:load />

当你在已安装 React 集成的 Astro 项目中直接添加应用时,许多应用程序将会作为完整的 React 应用程序运行。这是一个快速启动项目并在迁移到 Astro 过程中保持应用功能的绝佳方式。

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

以下是一些关键概念和迁移策略帮助你入门,也可以继续阅读我们的文档和参与我们的 Discord 社区 以获取更多帮助!

CRA 和 Astro 的关键相似之处

标题部分 CRA 和 Astro 的关键相似之处

CRA 和 Astro 的关键差异

标题部分 CRA 和 Astro 的关键差异

在用 Astro 重新构建 CRA 站点时,你会注意到一些重要的差异:

  • MPA vs SPA:CRA 是一个使用 index.js 作为项目根目录的单页面应用程序。Astro 是一个多页面站点,其中 index.astro 是你的首页。

  • .astro 组件 不是作为返回页面模板的导出函数而被构建。相反,你需要将代码分割到一个用于 JavaScript 的“代码围栏”和一个专门用于生成的 HTML 的“body”中。

  • 内容优先:Astro 的设计目标是展示你的内容,并允许你在需要时选择性地启用交互。如果现有的 CRA 应用用于构建高级的客户端交互,那么可能需要使用高级的 Astro 技术来让 .astro 组件来完成更具挑战性的复制,例如仪表板。

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

创建一个新的 Astro 项目

标题部分 创建一个新的 Astro 项目

通过你的包管理器来运行 create astro 命令启动 Astro 的 CLI 向导,并选择一个新的「空」Astro 项目。

终端窗口
npm create astro@latest

通过你的包管理器来运行 astro add 命令以添加 React 集成。如果你的应用程序使用了 Tailwind 或 MDX,你可以使用相同的命令添加多个 Astro 集成:

终端窗口
# 使用 NPM
npx astro add react
npx astro add react tailwind mdx
# 使用 Yarn
yarn astro add react
yarn astro add react tailwind mdx
# 使用 PNPM
pnpm astro add react
pnpm 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!

你可以在现有结构的基础上 使用 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;

将 JSX 文件转换为 .astro 文件

标题部分 将 JSX 文件转换为 .astro 文件

下面是将 CRA(Create React App)的 .js 组件转换为 .astro 组件的一些建议:

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

  2. 将任何 CRA 或 JSX 语法更改为 Astro 或 HTML 的标准规范。这包括 {children}className 等。

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

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

  5. 决定是否需要将任何导入的组件转换为 Astro。你可以将它们暂时保留为 React 组件,或永久保留为 React 组件。但是,如果它们不需要交互性,你可能最终会想将它们转换为 .astro 组件!

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

由于 Astro 输出原始的 HTML,因此可以使用构建步骤的输出来编写端到端测试。如果之前编写的端到端测试能够匹配 CRA 站点的标记,那么它们可能也可以直接使用。在 Astro 中,也可以导入和使用测试库(如 Jest 和 React Testing Library)来测试你的 React 组件。

了解更多详情,请参阅 Astro 的 测试指南

参考:将 CRA 语法转换为 Astro

标题部分 参考:将 CRA 语法转换为 Astro

在 Astro 中转换 CRA 导入语句

标题部分 在 Astro 中转换 CRA 导入语句

将任何 文件导入 准确地更新为相对引用的文件路径。可以通过使用 导入别名 或完整写出相对路径来实现。

注意,.astro 和其他一些文件类型必须使用它们的完整文件扩展名进行导入。

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

在 Astro 中转换 CRA 子组件属性

标题部分 在 Astro 中转换 CRA 子组件属性

将任何 {children} 实例转换为 Astro 的 <slot />。Astro 不需要将 {children} 作为函数属性来传递,它会自动在 <slot /> 中渲染子组件内容。

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

传递多组子元素的 React 组件可以通过使用 命名插槽 转换为 Astro 组件。

了解更多有关于 特定 <slot /> 用法 的内容。

在 Astro 中转换 CRA 数据获取

标题部分 在 Astro 中转换 CRA 数据获取

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

你需要移除任何副作用钩子(useEffect)的实例,然后使用 Astro.glob()getCollection()(或 getEntryBySlug())从项目源代码的其他文件中获取数据。

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

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

src/pages/index.astro
---
import { getCollection } from 'astro:content';
// 从 `src/content/blog/` 目录中获取所有条目
const allBlogPosts = await getCollection('blog');
// 从 `src/pages/posts/` 目录中获取所有条目
const allPosts = await Astro.glob('../pages/posts/*.md');
// 获取远程数据
const response = await fetch('https://randomuser.me/api/');
const data = await response.json();
const randomUser = data.results[0];
---

了解更多有关于 使用 Astro.glob()使用集合 API 查询 以及 获取远程数据 的内容。

在 Astro 中转换 CRA 样式

标题部分 在 Astro 中转换 CRA 样式

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

如有必要,将任何行内样式对象(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 集成,则可以支持 Tailwind,并且不需要更改现有的 Tailwind 代码!

了解更多有关于 Astro 中的样式 的内容。

你的 CRA 可能可以在 Astro 中正常工作!但是,你可能需要进行微小调整,以复制现有应用程序的功能和(或)样式。

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

更多迁移指南