如果你的应用具有现有框架无法很好地满足的约束,你更愿意构建自己的框架,或者你只是想学习 React 应用的基础知识,你可以从头开始构建 React 应用。
🌐 If your app has constraints not well-served by existing frameworks, you prefer to build your own framework, or you just want to learn the basics of a React app, you can build a React app from scratch.
深入研究
🌐 Consider using a framework
从零开始是一种轻松的使用 React 的方式,但需要注意的一个主要权衡是,这条路线通常等同于构建你自己的临时框架。随着你的需求发展,你可能需要解决更多类似框架的问题,而我们推荐的框架已经为这些问题提供了完善且支持良好的解决方案。
🌐 Starting from scratch is an easy way to get started using React, but a major tradeoff to be aware of is that going this route is often the same as building your own adhoc framework. As your requirements evolve, you may need to solve more framework-like problems that our recommended frameworks already have well developed and supported solutions for.
例如,如果将来你的应用需要支持服务器端渲染(SSR)、静态站点生成(SSG)和/或 React 服务器组件(RSC),你将必须自己实现这些功能。同样,如果未来的 React 功能需要在框架层进行集成,如果你想使用它们,也必须自己实现。
🌐 For example, if in the future your app needs support for server-side rendering (SSR), static site generation (SSG), and/or React Server Components (RSC), you will have to implement those on your own. Similarly, future React features that require integrating at the framework level will have to be implemented on your own if you want to use them.
我们推荐的框架也可以帮助你构建性能更好的应用。例如,减少或消除网络请求中的瀑布式调用可以带来更好的用户体验。当你在构建一个玩具项目时,这可能不是优先考虑的事项,但如果你的应用获得了用户,你可能希望提升其性能。
🌐 Our recommended frameworks also help you build better performing apps. For example, reducing or eliminating waterfalls from network requests makes for a better user experience. This might not be a high priority when you are building a toy project, but if your app gains users you may want to improve its performance.
采取这种方式也会使获得支持变得更加困难,因为你开发路由、数据获取和其他功能的方式将对你的情况是独一无二的。只有当你能够独自解决这些问题,或者你确信自己永远不需要这些功能时,才应该选择这个选项。
🌐 Going this route also makes it more difficult to get support, since the way you develop routing, data-fetching, and other features will be unique to your situation. You should only choose this option if you are comfortable tackling these problems on your own, or if you’re confident that you will never need these features.
有关推荐框架的列表,请查看 创建 React 应用。
🌐 For a list of recommended frameworks, check out Creating a React App.
步骤 1:安装构建工具
🌐 Step 1: Install a build tool
第一步是安装像 vite、parcel 或 rsbuild 这样的构建工具。这些构建工具提供打包和运行源代码的功能,为本地开发提供开发服务器,并提供将应用部署到生产服务器的构建命令。
🌐 The first step is to install a build tool like vite, parcel, or rsbuild. These build tools provide features to package and run source code, provide a development server for local development and a build command to deploy your app to a production server.
Vite
Vite 是一个构建工具,旨在为现代网页项目提供更快速、更精简的开发体验。
npm create vite@latest my-app -- --template react-tsVite 有一定的设计理念,并且开箱即用提供了合理的默认设置。Vite 拥有丰富的插件生态系统,以支持快速刷新、JSX、Babel/SWC 以及其他常见功能。参见 Vite 的 React 插件 或 React SWC 插件 以及 React SSR 示例项目 来入门。
🌐 Vite is opinionated and comes with sensible defaults out of the box. Vite has a rich ecosystem of plugins to support fast refresh, JSX, Babel/SWC, and other common features. See Vite’s React plugin or React SWC plugin and React SSR example project to get started.
Vite 已经作为构建工具在我们的一种推荐框架中使用:React Router。
🌐 Vite is already being used as a build tool in one of our recommended frameworks: React Router.
Parcel
Parcel 将出色的开箱即用开发体验与可扩展的架构结合起来,可以让你的项目从刚开始阶段发展到大规模生产应用。
npm install --save-dev parcelParcel开箱即支持快速刷新、JSX、TypeScript、Flow和样式。查看Parcel的React教程以开始使用。
🌐 Parcel supports fast refresh, JSX, TypeScript, Flow, and styling out of the box. See Parcel’s React recipe to get started.
Rsbuild
Rsbuild 是一个由 Rspack 提供支持的构建工具,为 React 应用提供无缝的开发体验。它配备了精心调整的默认设置和已准备好的性能优化。
npx create-rsbuild --template reactRsbuild 包含对 React 功能的内置支持,如快速刷新、JSX、TypeScript 和样式。请参见 Rsbuild 的 React 指南 开始使用。
🌐 Rsbuild includes built-in support for React features like fast refresh, JSX, TypeScript, and styling. See Rsbuild’s React guide to get started.
步骤 2:构建常见应用模式
🌐 Step 2: Build Common Application Patterns
上面列出的构建工具从仅限客户端的单页应用 (SPA) 开始,但不包括针对路由、数据获取或样式等常见功能的任何进一步解决方案。
🌐 The build tools listed above start off with a client-only, single-page app (SPA), but don’t include any further solutions for common functionality like routing, data fetching, or styling.
React 生态系统包含许多用于解决这些问题的工具。我们列出了一些广泛使用的工具作为起点,但如果其他工具对你更合适,也可以随意选择。
🌐 The React ecosystem includes many tools for these problems. We’ve listed a few that are widely used as a starting point, but feel free to choose other tools if those work better for you.
路由
🌐 Routing
路由决定了当用户访问特定 URL 时显示哪些内容或页面。你需要设置一个路由来将 URL 映射到应用的不同部分。你还需要处理嵌套路由、路由参数和查询参数。路由可以在代码中配置,也可以根据组件文件夹和文件结构定义。
🌐 Routing determines what content or pages to display when a user visits a particular URL. You need to set up a router to map URLs to different parts of your app. You’ll also need to handle nested routes, route parameters, and query parameters. Routers can be configured within your code, or defined based on your component folder and file structures.
路由是现代应用的核心部分,通常与数据获取(包括预取整个页面的数据以加快加载速度)、代码拆分(以最小化客户端包大小)和页面渲染方法(决定如何生成每个页面)集成。
🌐 Routers are a core part of modern applications, and are usually integrated with data fetching (including prefetching data for a whole page for faster loading), code splitting (to minimize client bundle sizes), and page rendering approaches (to decide how each page gets generated).
我们建议使用:
🌐 We suggest using:
数据获取
🌐 Data Fetching
从服务器或其他数据源获取数据是大多数应用的关键部分。正确执行此操作需要处理加载状态、错误状态以及缓存获取的数据,这可能很复杂。
🌐 Fetching data from a server or other data source is a key part of most applications. Doing this properly requires handling loading states, error states, and caching the fetched data, which can be complex.
专门构建的数据获取库为你完成了获取和缓存数据的繁重工作,让你能够专注于你的应用需要哪些数据以及如何展示这些数据。这些库通常直接在你的组件中使用,但也可以集成到路由加载器中,以实现更快的预取和更好的性能,同时也可用于服务器渲染。
🌐 Purpose-built data fetching libraries do the hard work of fetching and caching the data for you, letting you focus on what data your app needs and how to display it. These libraries are typically used directly in your components, but can also be integrated into routing loaders for faster pre-fetching and better performance, and in server rendering as well.
请注意,直接在组件中获取数据可能会导致加载时间变慢,因为会产生网络请求瀑布效应,因此我们建议尽可能在路由加载器或服务器端预获取数据! 这可以让页面的数据在页面显示时一次性获取完成。
🌐 Note that fetching data directly in components can lead to slower loading times due to network request waterfalls, so we recommend prefetching data in router loaders or on the server as much as possible! This allows a page’s data to be fetched all at once as the page is being displayed.
如果你从大多数后端或 REST 样式 API 获取数据,我们建议使用:
🌐 If you’re fetching data from most backends or REST-style APIs, we suggest using:
如果你从 GraphQL API 获取数据,我们建议使用:
🌐 If you’re fetching data from a GraphQL API, we suggest using:
代码拆分
🌐 Code-splitting
代码分拆是将应用分解为可以按需加载的更小包的过程。应用的代码随着每个新功能和额外依赖的增加而增大。应用可能会加载变慢,因为整个应用的所有代码在使用前都需要发送。缓存、减少功能/依赖以及将部分代码移动到服务器上运行可以帮助缓解加载缓慢的问题,但如果过度使用,这些都是不完整的解决方案,并可能牺牲功能。
🌐 Code-splitting is the process of breaking your app into smaller bundles that can be loaded on demand. An app’s code size increases with every new feature and additional dependency. Apps can become slow to load because all of the code for the entire app needs to be sent before it can be used. Caching, reducing features/dependencies, and moving some code to run on the server can help mitigate slow loading but are incomplete solutions that can sacrifice functionality if overused.
类似地,如果你依赖使用你的框架的应用来拆分代码,你可能会遇到加载速度比完全不拆分代码时还慢的情况。例如,懒加载图表会延迟发送渲染图表所需的代码,将图表代码与应用的其余部分分开。Parcel 支持使用 React.lazy 进行代码拆分。然而,如果图表在初次渲染后才加载其数据,你现在将需要等待两次。这就是一个瀑布式流程:你不能同时获取图表数据并发送渲染代码,而是必须等待每个步骤依次完成。
🌐 Similarly, if you rely on the apps using your framework to split the code, you might encounter situations where loading becomes slower than if no code splitting were happening at all. For example, lazily loading a chart delays sending the code needed to render the chart, splitting the chart code from the rest of the app. Parcel supports code splitting with React.lazy. However, if the chart loads its data after it has been initially rendered you are now waiting twice. This is a waterfall: rather than fetching the data for the chart and sending the code to render it simultaneously, you must wait for each step to complete one after the other.
通过按路由拆分代码,并与打包和数据获取集成,可以减少应用的初始加载时间以及应用最大可见内容渲染所需的时间(最大内容绘制)。
🌐 Splitting code by route, when integrated with bundling and data fetching, can reduce the initial load time of your app and the time it takes for the largest visible content of the app to render (Largest Contentful Paint).
有关代码拆分说明,请参阅你的构建工具文档:
🌐 For code-splitting instructions, see your build tool docs:
提高应用性能
🌐 Improving Application Performance
由于你选择的构建工具仅支持单页应用(SPA),你需要实现其他渲染模式,例如服务器端渲染(SSR)、静态站点生成(SSG)和/或 React 服务器组件(RSC)。即使你一开始不需要这些功能,将来可能会有一些路由会受益于 SSR、SSG 或 RSC。
🌐 Since the build tool you select only supports single page apps (SPAs), you’ll need to implement other rendering patterns like server-side rendering (SSR), static site generation (SSG), and/or React Server Components (RSC). Even if you don’t need these features at first, in the future there may be some routes that would benefit SSR, SSG or RSC.
- 单页应用(SPA) 加载单个 HTML 页面,并在用户与应用互动时动态更新页面。SPA 更容易上手,但它们的初始加载时间可能较慢。SPA 是大多数构建工具的默认架构。
- 流式服务器端渲染(SSR) 在服务器上渲染页面并将完整渲染的页面发送到客户端。SSR 可以提升性能,但其设置和维护可能比单页面应用更复杂。加入流式功能后,SSR 的设置和维护可能会非常复杂。详见 Vite 的 SSR 指南。
- 静态网站生成 (SSG) 在构建时为你的应用生成静态 HTML 文件。SSG 可以提高性能,但其设置和维护可能比服务器端渲染更复杂。请参阅 Vite 的 SSG 指南。
- React 服务器组件 (RSC) 让你在单个 React 树中混合使用构建时、仅服务器以及交互式组件。RSC 可以提升性能,但目前需要深入的专业知识来进行设置和维护。参见 Parcel 的 RSC 示例。
你的渲染策略需要与你的路由集成,以便使用你的框架构建的应用可以在每个路由级别选择渲染策略。这将使不同的渲染策略成为可能,而无需重写整个应用。例如,你的应用的登录页可能适合静态生成(SSG),而带有内容源的页面可能在服务器端渲染下表现最佳。
🌐 Your rendering strategies need to integrate with your router so apps built with your framework can choose the rendering strategy on a per-route level. This will enable different rendering strategies without having to rewrite your whole app. For example, the landing page for your app might benefit from being statically generated (SSG), while a page with a content feed might perform best with server-side rendering.
为正确的路由使用正确的渲染策略可以减少内容第一个字节加载的时间(首字节时间)、第一个内容呈现的时间(首次内容绘制)以及应用最大可见内容呈现的时间(最大内容绘制)。
🌐 Using the right rendering strategy for the right routes can decrease the time it takes for the first byte of content to be loaded (Time to First Byte), the first piece of content to render (First Contentful Paint), and the largest visible content of the app to render (Largest Contentful Paint).
还有更多…
🌐 And more…
这些只是新应用在从零开始构建时需要考虑的一些功能示例。许多你会遇到的限制可能很难解决,因为每个问题彼此互相关联,并且可能需要在你不熟悉的问题字段具备深厚的专业知识。
🌐 These are just a few examples of the features a new app will need to consider when building from scratch. Many limitations you’ll hit can be difficult to solve as each problem is interconnected with the others and can require deep expertise in problem areas you may not be familiar with.
如果你不想自己解决这些问题,你可以使用一个提供开箱即用功能的框架来开始。
🌐 If you don’t want to solve these problems on your own, you can get started with a framework that provides these features out of the box.