deno.com
本页内容

使用入门模板构建 React 应用

React 是最广泛使用的 JavaScript 前端库。

在本教程中,我们将使用 Deno 构建一个简单的 React 应用。该应用将显示恐龙列表。当你点击其中一个时,它会带你进入一个恐龙页面,其中包含更多详细信息。你可以在 GitHub 上查看已完成的应用仓库

demo of the app

本教程将使用 Vite 在本地提供应用服务。Vite 是一个用于现代 Web 项目的构建工具和开发服务器。它与 React 和 Deno 配合良好,利用 ES 模块并允许你直接导入 React 组件。

入门应用 跳转到标题

我们已经为你设置了一个入门模板。这将设置一个基本的入门应用,包含 React、Vite 和一个 deno.json 文件供你配置项目。访问 GitHub 仓库 https://github.com/denoland/react-vite-ts-template 并点击“Use this template”(使用此模板)按钮来创建一个新仓库。

从模板创建新仓库后,将其克隆到本地机器并导航到项目目录。

在本地克隆仓库 跳转到标题

git clone https://github.com/your-username/your-repo-name.git
cd your-repo-name

安装依赖项 跳转到标题

通过运行以下命令安装项目依赖项:

deno install

运行开发服务器 跳转到标题

现在你可以通过运行以下命令来服务你的新 React 应用

deno run dev

这将启动 Vite 服务器,点击输出中的 localhost 链接即可在浏览器中查看你的应用。

关于模板 跳转到标题

你克隆的模板仓库包含一个基本的 React 应用。该应用使用 Vite 作为开发服务器,并提供一个使用 oak 构建的静态文件服务器,它将在部署时提供构建好的应用。React 应用位于 client 文件夹中,后端服务器位于 server 文件夹中。

deno.json 文件用于配置项目并指定运行应用所需的权限,它包含 tasks 字段,该字段定义了可以使用 deno run 运行的任务。它有一个 dev 任务用于运行 Vite 服务器,一个 build 任务用于使用 Vite 构建应用,以及一个 serve 任务用于运行后端服务器以提供构建好的应用。

添加后端 API 跳转到标题

我们将在模板提供的服务器中构建一个 API。这将是我们获取恐龙数据的地方。

在你新项目的 server 目录中,创建一个 api 文件夹。在该文件夹中,创建一个 data.json 文件,它将包含硬编码的恐龙数据。

此 JSON 文件复制并粘贴到 api/data.json 文件中。(如果你正在构建一个真实的应用,你可能会从数据库或外部 API 获取这些数据。)

我们将在模板附带的服务器中构建一些返回恐龙信息的 API 路由,我们需要 cors 中间件 来启用 CORS

使用 deno install 命令将 cors 依赖项添加到你的项目

deno install jsr:@tajpouria/cors

接下来,更新 server/main.ts 以导入所需模块并创建一个新的 Router 实例来定义一些路由

main.ts
import { Application } from "jsr:@oak/oak/application";
import { Router } from "jsr:@oak/oak/router";
import { oakCors } from "@tajpouria/cors";
import routeStaticFilesFrom from "./util/routeStaticFilesFrom.ts";
import data from "./api/data.json" with { type: "json" };

export const app = new Application();
const router = new Router();

之后,在同一文件中,我们将定义两个路由。一个在 /api/dinosaurs 返回所有恐龙,另一个在 /api/dinosaurs/:dinosaur 根据 URL 中的名称返回特定的恐龙。

main.ts
router.get("/api/dinosaurs", (context) => {
  context.response.body = data;
});

router.get("/api/dinosaurs/:dinosaur", (context) => {
  if (!context?.params?.dinosaur) {
    context.response.body = "No dinosaur name provided.";
  }

  const dinosaur = data.find((item) =>
    item.name.toLowerCase() === context.params.dinosaur.toLowerCase()
  );

  context.response.body = dinosaur ?? "No dinosaur found.";
});

在同一文件的底部,将我们刚刚定义的路由附加到应用程序。我们还必须包含模板中的静态文件服务器,最后我们将启动服务器监听 8000 端口。

main.ts
app.use(oakCors());
app.use(router.routes());
app.use(router.allowedMethods());
app.use(routeStaticFilesFrom([
  `${Deno.cwd()}/client/dist`,
  `${Deno.cwd()}/client/public`,
]));

if (import.meta.main) {
  console.log("Server listening on port https://:8000");
  await app.listen({ port: 8000 });
}

你可以使用 deno run --allow-env --allow-net --allow-read server/main.ts 命令运行 API 服务器。我们将创建一个任务来在后台运行此命令,并更新开发任务以同时运行 React 应用和 API 服务器。

在你的 deno.json 文件中,更新 tasks 字段以包含以下内容:

deno.json
{
  "tasks": {
+   "dev": "deno run -A npm:vite & deno run server:start",
    "build": "deno run -A npm:vite build",
    "server:start": "deno run -A --node-modules-dir --watch ./server/main.ts",
    "serve": "deno run build && deno run server:start"
},
+ "nodeModulesDir": "auto",

如果你现在运行 deno run dev 并访问 localhost:8000/api/dinosaurs,你的浏览器中应该会看到所有恐龙的 JSON 响应。

更新入口点 跳转到标题

React 应用的入口点位于 client/src/main.tsx 文件中。我们的将非常基础

main.tsx
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import "./index.css";
import App from "./App.tsx";

createRoot(document.getElementById("root")!).render(
  <StrictMode>
    <App />
  </StrictMode>,
);

添加路由器 跳转到标题

该应用将有两个路由://:dinosaur

我们将使用 react-router-dom 来构建一些路由逻辑,因此我们需要将 react-router-dom 依赖项添加到你的项目。在项目根目录运行

deno install npm:react-router-dom

更新 /src/App.tsx 文件,导入并使用 react-router-dom 中的 BrowserRouter 组件,并定义这两个路由

App.tsx
import { BrowserRouter, Route, Routes } from "react-router-dom";
import Index from "./pages/index.tsx";
import Dinosaur from "./pages/Dinosaur.tsx";
import "./App.css";

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Index />} />
        <Route path="/:selectedDinosaur" element={<Dinosaur />} />
      </Routes>
    </BrowserRouter>
  );
}

export default App;

代理转发 API 请求 跳转到标题

Vite 将在 3000 端口提供应用程序服务,而我们的 API 在 8000 端口运行。因此,我们需要设置一个代理,以允许路由器可以访问 api/ 路径。将代理设置添加到 vite.config.ts

vite.config.ts
export default defineConfig({
  root: "./client",
  server: {
    port: 3000,
+   proxy: {
+     "/api": {
+       target: "https://:8000",
+       changeOrigin: true,
+     },
+   },

创建页面 跳转到标题

我们将创建两个页面:IndexDinosaurIndex 页面将列出所有恐龙,Dinosaur 页面将显示特定恐龙的详细信息。

src 目录中创建一个 pages 文件夹,并在其中创建两个文件:index.tsxDinosaur.tsx

类型 跳转到标题

这两个页面都将使用 Dino 类型来描述它们从 API 期望的数据形状,因此让我们在 src 目录中创建一个 types.ts 文件

types.ts
export type Dino = { name: string; description: string };

index.tsx 跳转到标题

此页面将从 API 获取恐龙列表并将其渲染为链接

index.tsx
import { useEffect, useState } from "react";
import { Link } from "react-router-dom";
import { Dino } from "../types.ts";

export default function Index() {
  const [dinosaurs, setDinosaurs] = useState<Dino[]>([]);

  useEffect(() => {
    (async () => {
      const response = await fetch(`/api/dinosaurs/`);
      const allDinosaurs = await response.json() as Dino[];
      setDinosaurs(allDinosaurs);
    })();
  }, []);

  return (
    <main>
      <h1>Welcome to the Dinosaur app</h1>
      <p>Click on a dinosaur below to learn more.</p>
      {dinosaurs.map((dinosaur: Dino) => {
        return (
          <Link
            to={`/${dinosaur.name.toLowerCase()}`}
            key={dinosaur.name}
            className="dinosaur"
          >
            {dinosaur.name}
          </Link>
        );
      })}
    </main>
  );
}

Dinosaur.tsx 跳转到标题

此页面将从 API 获取特定恐龙的详细信息并将其渲染为段落

Dinosaur.tsx
import { useEffect, useState } from "react";
import { Link, useParams } from "react-router-dom";
import { Dino } from "../types";

export default function Dinosaur() {
  const { selectedDinosaur } = useParams();
  const [dinosaur, setDino] = useState<Dino>({ name: "", description: "" });

  useEffect(() => {
    (async () => {
      const resp = await fetch(`/api/dinosaurs/${selectedDinosaur}`);
      const dino = await resp.json() as Dino;
      setDino(dino);
    })();
  }, [selectedDinosaur]);

  return (
    <div>
      <h1>{dinosaur.name}</h1>
      <p>{dinosaur.description}</p>
      <Link to="/">🠠 Back to all dinosaurs</Link>
    </div>
  );
}

恐龙列表样式 跳转到标题

由于我们将在主页显示恐龙列表,让我们进行一些基本格式化。将以下内容添加到 src/App.css 底部,以有序方式显示我们的恐龙列表

src/App.css
.dinosaur {
  display: block;
}

运行应用 跳转到标题

要运行该应用,请使用你之前设置的任务

deno run dev

在浏览器中导航到本地 Vite 服务器(localhost:3000),你应该会看到恐龙列表,你可以点击它们来了解每个恐龙的详细信息。

demo of the app

构建和部署 跳转到标题

你克隆的模板带有一个 serve 任务,它会构建应用并使用后端服务器提供服务。运行以下命令来构建和提供应用服务:

deno run serve

如果你在浏览器中访问 localhost:8000,你应该会看到应用正在运行!

你可以将此应用部署到你喜欢的云服务提供商。我们推荐使用 Deno Deploy,以获得简单易用的部署体验。

要部署到 Deno Deploy,请访问 Deno Deploy 控制台并创建一个新项目。然后,你可以通过连接你的 GitHub 仓库并选择要部署的分支来部署应用。

为项目命名,并确保 build step(构建步骤)设置为 deno run build,并且 Entrypoint(入口点)是 server/main.ts

点击 Deploy Project(部署项目)按钮,你的应用就会上线!

🦕 现在你可以使用 Vite 和 Deno 脚手架并开发 React 应用了!你已准备好构建极速的 Web 应用程序。我们希望你喜欢探索这些尖端工具,我们迫不及待地想看到你的作品!

您找到所需内容了吗?

隐私政策