建立 React 项目
React 应用需要一些工具配置才能运行代码。需要有东西把 JSX 转换成浏览器能执行的 JavaScript,还要有东西在你开发时提供这些代码。Vite 做这两件事,大约三十秒内就能搭建一个可用的项目。这章会带你从一个空文件夹走到一个运行的应用,然后追踪最重要的流程:一个组件是如何最终显示在屏幕上的。
创建项目
Vite 是一个内置项目生成器的构建工具。用 npm create 运行它,回答两个提示,你就有了一个项目:
npm create vite@latest my-react-app
cd my-react-app
npm install
npm run dev第一个命令会问你要用哪个框架(选择 React)和哪个变种(选择 JavaScript,或者如果你用的话选择 TypeScript)。它会生成一个叫 my-react-app 的文件夹,里面有 React 项目需要的一切。npm install 下载 package.json 中列出的依赖,React 本身就来自这里。npm run dev 启动开发服务器并打印本地地址,通常是 http://localhost:5173。在浏览器中打开这个地址,启动应用就在运行了。
生成的文件夹有一些早期重要的文件:
index.html:浏览器加载的单个 HTML 页面。src/main.jsx:入口点,React 在这里附加到页面上。src/App.jsx:你的顶层组件,也是你最先编辑的文件。src/assets/:你导入到组件中的图片和其他静态文件。package.json:依赖和dev、build、preview脚本。vite.config.js:构建配置,你可以长期不用管它。
各部分是如何连接的
三个文件以直线方式相互交接。从 index.html 开始,它故意几乎是空的:
<body>
<div id="root"></div>
<!-- 后面跟着一个 <script type="module" src="/src/main.jsx"> 标签 -->
</body>那个空的 <div id="root"> 是页面上 React 允许填充的位置。你的应用渲染的所有东西都放在它里面。下面的 module <script> 标签加载 main.jsx,这是 React 接手的地方:
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import App from './App.jsx'
import './index.css'
createRoot(document.getElementById('root')).render(
<StrictMode>
<App />
</StrictMode>
)从右往左读这个调用。document.getElementById('root') 找到空 div。createRoot 把它包装在 React 根中,意思是 React 现在拥有那个元素的内容,并且会让它与你的组件保持同步。.render(...) 告诉它放什么在那里:App 组件。
<StrictMode> 是一个仅在开发中的包装器,对它里面的所有东西运行额外检查,并对可能导致 bug 的模式发出警告。它不给页面添加任何东西,在生产构建中会关闭。它最明显的效果出现在 Effects 中,它故意在开发中挂载每个组件两次。
App.jsx 是一个导出自己的普通组件:
export default function App() {
return <h1>Hello from React</h1>
}这就是整个流程。浏览器加载 index.html,脚本加载 main.jsx,main.jsx 在根 div 上调用 createRoot 并渲染 <App />,App 返回成为你看到的标题的 JSX。从现在开始你写的每个组件都坐在 App 内部的某个地方,所以它通过同样的路径到达页面。main.jsx 通常只写一次,很少再被改动;几乎所有你的工作都发生在 App.jsx 和它引入的组件中。
版本说明
React 17 及更早版本使用 ReactDOM.render(<App />, document.getElementById('root')) 作为入口点。React 18 引入了 createRoot,它打开了并发渲染,并让旧的调用继续工作,但带着弃用警告。React 19 删除了它,所以 ReactDOM.render 现在会抛出错误。在仍然使用它的教程中,createRoot 是应该写在它位置上的行。详见 历史和版本 了解什么改变了。
开发服务器
npm run dev 启动 Vite 的开发服务器,在你开发时它会一直在终端运行。它的工作是为你的应用提供服务并对你的编辑做出反应。
保存对 App.jsx 的更改,浏览器会几乎立即更新,不需要手动刷新。这是热模块替换:Vite 把改变的模块推送到页面并交换到位,让应用的其余部分继续运行。一个你点到七的计数器在编辑后通常仍然读七,所以你在调整周围的标记时保留已经设置的任何状态。有些更改仍然会强制完整重新加载,Vite 会为你决定。
项目还有另外两个脚本。npm run build 在 dist 文件夹中产生一个优化的包,这是你部署的东西。npm run preview 本地提供那个构建的输出,所以你可以在发货前检查它。在开发期间,npm run dev 是你唯一需要的。
导入静态资源
图片放在 src/assets 下,通过 import 进入组件:
import logo from './assets/logo.png'
export default function Header() {
return <img src={logo} alt="Company logo" />
}导入给你一个变量,它持有那个图片的最终 URL,然后你在 src 中用花括号把它传递进去。把 src="./assets/logo.png" 写成纯字符串往往会出问题,因为你的源文件夹中的路径很少是构建输出中的路径。
导入文件而不是这样做会让构建工具参与进来。它看到你的代码依赖 logo.png,把它复制到输出中,并把那个文件最终在的 URL 给你回来。把你的组件移到不同的文件夹,相对导入仍然能解析。拼错文件名,你会立即发现,因为导入失败了,而不是在生产中发现一个破碎的图片。同样的模式适用于 SVG、字体和任何构建工具知道如何处理的其他文件。
index.html 有一个 id 为 root 的空 div,main.jsx 用 createRoot 抓住那个 div 并把 <App /> 渲染进去,App.jsx 是说出什么出现的组件。一旦你能追踪那条路径,你就确切知道你自己的代码在哪里接入。 接下来:组件,你将用来填充那个 App.jsx 的构建块。

