从 Create React App (CRA) 迁移
Astro 的 React 集成 支持在 Astro 组件内部使用 React 组件,包括像 Create React App (CRA) 这样的完整 React 应用!
---// Import your root App componentimport App from '../cra-project/App.jsx';---<!-- Use a client directive to load your app --><App client:load />
当你将许多应用直接添加到已安装 React 集成的 Astro 项目中时,它们会作为完整的 React 应用“开箱即用”。这是让你的项目立即启动并运行,并在迁移到 Astro 的同时保持应用功能的好方法。
随着时间的推移,你可以将你的结构逐步转换为 .astro
和 .jsx
组件的组合。你可能会发现你需要的 React 组件比你想象的要少!
这里有一些关键概念和迁移策略可以帮助你入门。利用我们文档的其余部分和我们的 Discord 社区 继续前进!
CRA 和 Astro 之间的主要相似之处
标题为“CRA 和 Astro 之间的主要相似之处”的部分-
.astro
文件的语法与 JSX 相似。编写 Astro 应该会感觉很熟悉。 -
Astro 使用基于文件的路由,并允许特殊命名的页面创建动态路由。
-
Astro 是基于组件的,你的标记结构在迁移前后会很相似。
-
Astro 有针对 React、Preact 和 Solid 的官方集成,所以你可以使用现有的 JSX 组件。请注意,在 Astro 中,这些文件必须具有
.jsx
或.tsx
扩展名。 -
Astro 支持安装 NPM 包,包括 React 库。你现有的许多依赖项都可以在 Astro 中工作。
CRA 和 Astro 之间的主要区别
标题为“CRA 和 Astro 之间的主要区别”的部分当你在 Astro 中重建你的 CRA 网站时,你会注意到一些重要的区别
-
CRA 是一个单页应用,使用
index.js
作为项目的根。Astro 是一个多页网站,index.astro
是你的主页。 -
.astro
组件不是作为返回页面模板的导出函数编写的。相反,你会将代码分割成用于 JavaScript 的“代码栅栏”和一个专门用于生成 HTML 的主体。 -
内容驱动:Astro 的设计初衷是展示你的内容,并允许你仅在需要时选择性地加入交互性。现有的 CRA 应用可能是为高客户端交互性而构建的,可能需要高级的 Astro 技术来包含使用
.astro
组件更难复制的项目,例如仪表盘。
将你的 CRA 添加到 Astro
标题为“将你的 CRA 添加到 Astro”的部分你现有的应用可以直接在新的 Astro 项目中渲染,通常无需更改应用代码。
创建一个新的 Astro 项目
标题为“创建一个新的 Astro 项目”的部分使用你的包管理器的 create astro
命令启动 Astro 的 CLI 向导,并选择一个新的“空” Astro 项目。
npm create astro@latest
pnpm create astro@latest
yarn create astro@latest
添加集成和依赖项
标题为“添加集成和依赖项”的部分使用你的包管理器的 astro add
命令添加 React 集成。如果你的应用使用 astro add
命令支持的其他包,如 Tailwind 和 MDX,你可以用一个命令将它们全部添加
npx astro add reactnpx astro add react tailwind mdx
pnpm astro add reactpnpm astro add react tailwind mdx
yarn astro add reactyarn astro add react tailwind mdx
如果你的 CRA 需要任何依赖项(例如 NPM 包),则通过命令行单独安装它们,或者将它们手动添加到新 Astro 项目的 package.json
中,然后运行安装命令。请注意,许多(但不是所有)React 依赖项都可以在 Astro 中工作。
添加你现有的应用文件
标题为“添加你现有的应用文件”的部分将你现有的 Create React App (CRA) 项目源文件和文件夹(例如 components
、hooks
、styles
等)复制到 src/
内的一个新文件夹中,保持其文件结构,以便你的应用能继续工作。请注意,所有 .js
文件扩展名都必须重命名为 .jsx
或 .tsx
。
不要包含任何配置文件。你将使用 Astro 自己的 astro.config.mjs
、package.json
和 tsconfig.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 />
组件
---import App from '../cra-project/App.jsx';---<App client:load />
你的应用需要一个 客户端指令 来实现交互性。Astro 会将你的 React 应用渲染为静态 HTML,直到你选择启用客户端 JavaScript。
使用 client:load
来确保你的应用立即从服务器加载,或者使用 client:only="react"
来跳过服务器端渲染,并完全在客户端运行你的应用。
将你的 CRA 转换为 Astro
标题为“将你的 CRA 转换为 Astro”的部分在将你现有的应用添加到 Astro 之后,你可能想将你的应用本身转换为 Astro!
你将复制一个类似的基于组件的设计,使用 Astro HTML 模板组件作为你的基本结构,同时为交互岛导入和包含单个 React 组件(这些组件本身可能就是完整的应用!)。
每次迁移都会有所不同,并且可以增量进行,而不会中断你正在运行的应用。按照自己的节奏转换各个部分,这样随着时间的推移,你的应用将越来越多地由 Astro 组件驱动。
在转换你的 React 应用时,你将决定哪些 React 组件要重写为 Astro 组件。你唯一的限制是 Astro 组件可以导入 React 组件,但 React 组件只能导入其他 React 组件
---import MyReactComponent from '../components/MyReactComponent.jsx';---<html> <body> <h1>Use React components directly in Astro!</h1> <MyReactComponent /> </body></html>
你可以将 React 组件嵌套在单个 Astro 组件中,而不是将 Astro 组件导入到 React 组件中
---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 组件可能会对你有所帮助。
比较:JSX 与 Astro
标题为“比较:JSX 与 Astro”的部分比较下面的 CRA 组件和相应的 Astro 组件
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;
---import Header from './Header.astro';import Footer from './Footer.astro';import './layout.css';const res = await fetch('https://api.github.com/repos/withastro/astro')const json = await res.json();const message = json.message;const stars = json.stargazers_count || 0;---<Header /><p class="banner">Astro has {stars} 🧑🚀</p><Footer /><style> .banner { background-color: #f4f4f4; padding: 1em 1.5em; text-align: center; margin-bottom: 1em; }</style>
将 JSX 文件转换为 .astro
文件
标题为“将 JSX 文件转换为 .astro 文件”的部分以下是将 CRA .js
组件转换为 .astro
组件的一些技巧
-
使用现有 CRA 组件函数返回的 JSX 作为你的 HTML 模板的基础。
-
将任何 CRA 或 JSX 语法转换为 Astro 或 HTML Web 标准。例如,这包括
{children}
和className
。 -
将任何必要的 JavaScript(包括导入语句)移动到“代码栅栏”(
---
)中。注意:用于条件性渲染内容的 JavaScript 通常直接写在 Astro 的 HTML 模板中。 -
使用
Astro.props
访问之前传递给你的 CRA 函数的任何附加 props。 -
决定是否需要将任何导入的组件也转换为 Astro。你现在或永远都可以将它们保留为 React 组件。但是,你最终可能希望将它们转换为
.astro
组件,特别是如果它们不需要交互的话! -
用导入语句或
import.meta.glob()
替换useEffect()
来查询本地文件。使用fetch()
来获取外部数据。
迁移测试
标题为“迁移测试”的部分由于 Astro 输出原始 HTML,因此可以使用构建步骤的输出来编写端到端测试。如果你能够匹配 CRA 站点的标记,那么以前编写的任何端到端测试都可能开箱即用。像 Jest 和 React Testing Library 这样的测试库可以被导入并在 Astro 中使用,以测试你的 React 组件。
更多信息请参阅 Astro 的测试指南。
参考:将 CRA 语法转换为 Astro
标题为“参考:将 CRA 语法转换为 Astro”的部分CRA 导入到 Astro
标题为“CRA 导入到 Astro”的部分更新任何文件导入,以精确引用相对文件路径。这可以通过使用导入别名或完整写出相对路径来完成。
请注意,.astro
和其他几种文件类型必须使用其完整的文件扩展名进行导入。
---import Card from '../../components/Card.astro';---<Card />
CRA Children Props 到 Astro
标题为“CRA Children Props 到 Astro”的部分将任何 {children}
的实例转换为 Astro 的 <slot />
。Astro 不需要以函数 prop 的形式接收 {children}
,它会自动在 <slot />
中渲染子内容。
------export default function MyComponent(props) { return ( <div> {props.children} </div> );}
<div> <slot /></div>
传递多组子组件的 React 组件可以使用命名插槽迁移到 Astro 组件。
查看更多关于Astro 中 <slot />
的具体用法。
CRA 数据获取到 Astro
标题为“CRA 数据获取到 Astro”的部分在 Create React App 组件中获取数据与在 Astro 中类似,但有一些细微的差别。
你需要移除任何副作用钩子(useEffect
)的实例,改用 import.meta.glob()
或 getCollection()
/getEntry()
来访问项目源中其他文件的数据。
要获取远程数据,请使用 fetch()
。
这些数据请求在 Astro 组件的 frontmatter 中进行,并使用顶层 await。
---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 }));
// Fetch remote dataconst response = await fetch('https://randomuser.me/api/');const data = await response.json();const randomUser = data.results[0];---
查看更多关于使用 import.meta.glob()
导入本地文件、使用 Collections API 查询或获取远程数据的信息。
CRA 样式到 Astro
标题为“CRA 样式到 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 代码进行任何更改!
查看更多关于在 Astro 中设置样式的信息。
故障排除
标题为“问题排查”的部分你的 CRA 可能在 Astro 中“开箱即用”!但是,你很可能需要进行一些微调来复制现有应用的功能和/或样式。
如果你在本文档中找不到答案,请访问 Astro Discord 并在我们的支持论坛中提问!
社区资源
标题为“社区资源”的部分如果你发现(或制作了!)一个关于将 Create React App 转换为 Astro 的有用视频或博客文章,请将其添加到此列表!