Spec-Zone.ru › Deno 2

Создайте приложение React с create-vite

React — это наиболее широко используемая JavaScript-библиотека для фронтенда.

В этом руководстве мы создадим простое приложение React с Deno. Приложение будет отображать список динозавров. При нажатии на одного из них вы перейдёте на страницу динозавра с более подробной информацией. Вы можете посмотреть готовый репозиторий приложения на GitHub.

demo of the app

Создайте приложение React с Vite и Deno

В этом руководстве мы будем использовать create-vite для быстрого создания приложения Deno и React. Vite — это инструмент сборки и сервер разработки для современных веб-проектов. Он хорошо сочетается с React и Deno, использует ES-модули и позволяет вам импортировать компоненты React напрямую.

В терминале выполните следующую команду, чтобы создать новое приложение React с Vite, используя шаблон typescript:

deno run -A npm:create-vite@latest --template react-ts

При запросе присвойте вашему приложению имя и cd в только что созданную папку проекта. Затем выполните следующую команду, чтобы установить зависимости:

deno install

Теперь вы можете запустить ваше новое приложение react, выполнив:

deno task dev

Это запустит сервер Vite, нажмите на ссылку вывода в локальном хосте, чтобы увидеть ваше приложение в браузере. Если у вас установлен расширение Deno для VSCode, вы можете заметить, что редактор выделяет некоторые ошибки в коде. Это потому, что приложение, созданное Vite, разработано с Node в виду и поэтому использует соглашения, которых нет в Deno (например, «небрежные импорты» — импорт модулей без расширения файла). Отключите расширение Deno для этого проекта, чтобы избежать этих ошибок, или попробуйте руководство по созданию приложения React с файлом deno.json.

Добавление бэкенда

Следующим шагом является добавление API бэкенда. Мы создадим очень простой API, возвращающий информацию о динозаврах.

В корне вашего нового проекта создайте папку api. В этой папке создайте файл main.ts, который запустит сервер, и файл data.json, который будет содержать жёстко закодированные данные динозавров.

Скопируйте и вставьте этот JSON-файл в файл api/data.json.

Мы собираемся создать простой сервер API с маршрутами, возвращающими информацию о динозаврах. Мы будем использовать oak фреймворк для мидлверов и cors мидлвер, чтобы включить CORS.

Используйте команду deno add для добавления необходимых зависимостей в ваш проект:

deno add jsr:@oak/oak jsr:@tajpouria/cors

Далее, обновите api/main.ts для импорта необходимых модулей и создания новой Router инстанции для определения некоторых маршрутов:

main.ts
import { Application, Router } from "@oak/oak";
import { oakCors } from "@tajpouria/cors";
import data from "./data.json" with { type: "json" };

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.";
});

Наконец, внизу того же файла создайте новый Application экземпляр и прикрепите определённые маршруты к приложению с помощью app.use(router.routes()) и запустите сервер, прослушивая порт 8000:

main.ts
const app = new Application();
app.use(oakCors());
app.use(router.routes());
app.use(router.allowedMethods());

await app.listen({ port: 8000 });

Вы можете запустить сервер API с помощью deno run --allow-env --allow-net api/main.ts. Мы создадим задачу для выполнения этой команды в фоновом режиме и обновим задачу разработки, чтобы запустить как приложение React, так и сервер API.

В вашем файле package.json обновите поле scripts для включения следующего:

{
  "scripts": {
    "dev": "deno task dev:api & deno task dev:vite",
    "dev:api": "deno run --allow-env --allow-net api/main.ts",
    "dev:vite": "deno run -A npm:vite",
    // ...
}

Если вы запустите deno task dev сейчас и посетите localhost:8000/api/dinosaurs, в вашем браузере вы должны увидеть JSON-ответ со всеми динозаврами.

Обновление точки входа

Точка входа для приложения React находится в файле src/main.tsx. Наш будет очень простым:

main.tsx
import ReactDOM from "react-dom/client";
import App from "./App";
import "./index.css";

ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
  <App />,
);

Добавление роутера

Приложение будет иметь два маршрута: / и /:dinosaur.

Мы будем использовать react-router-dom, чтобы построить логику маршрутизации, поэтому нам нужно добавить зависимость react-router-dom в ваш проект. В корне проекта выполните:

deno add npm:react-router-dom

Обновите файл /src/App.tsx для импорта и использования компонента BrowserRouter из react-router-dom и определения двух маршрутов:

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

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

export default App;

Прокси для перенаправления запросов к API

Vite будет обслуживать приложение на порту 5173, а наш API работает на порту 8000. Поэтому нам нужно настроить прокси, чтобы разрешить api/-маршрутам быть доступными роутеру. Перезапишите vite.config.ts следующим, чтобы настроить прокси:

vite.config.ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";

export default defineConfig({
  plugins: [react()],
  server: {
    proxy: {
      "/api": {
        target: "http://localhost:8000",
        changeOrigin: true,
      },
    },
  },
});

Создание страниц

Мы создадим две страницы: Index и Dinosaur. Страница Index будет отображать список всех динозавров, а страница Dinosaur — подробности о конкретном динозавре.

Создайте папку pages в каталоге src и внутри неё два файла: index.tsx и Dinosaur.tsx.

Типы

Обе страницы будут использовать тип Dino для описания формы данных, которые они ожидают от API, поэтому давайте создадим файл types.ts в каталоге src:

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 task dev

Перейдите по ссылке локального сервера Vite в вашем браузере (localhost:5173) и вы должны увидеть список динозавров, по которому вы можете нажать, чтобы узнать о каждом из них.

demo of the app

Сборка и развертывание

На данный момент приложение обслуживается сервером разработки Vite. Чтобы обслуживать приложение в режиме производства, вы можете собрать приложение с помощью Vite, а затем обслуживать созданные файлы с помощью Deno. Для этого нам нужно обновить сервер API для обслуживания созданных файлов. Мы напишем мидлвер для этого. В вашем каталоге api создайте новую папку util и новый файл под названием routeStaticFilesFrom.ts и добавьте следующий код:

routeStaticFilesFrom.ts
import { Next } from "jsr:@oak/oak/middleware";
import { Context } from "jsr:@oak/oak/context";

// Configure static site routes so that we can serve
// the Vite build output and the public folder
export default function routeStaticFilesFrom(staticPaths: string[]) {
  return async (context: Context<Record<string, object>>, next: Next) => {
    for (const path of staticPaths) {
      try {
        await context.send({ root: path, index: "index.html" });
        return;
      } catch {
        continue;
      }
    }

    await next();
  };
}

Этот мидлвер попытается обслуживать статические файлы из путей, указанных в массиве staticPaths. Если файл не найден, он вызовет следующий мидлвер в цепочке. Теперь мы можем обновить файл api/main.ts для использования этого мидлвера:

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

const router = new Router();

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 ? dinosaur : "No dinosaur found.";
});

const app = new Application();
app.use(oakCors());
app.use(router.routes());
app.use(router.allowedMethods());
app.use(routeStaticFilesFrom([
  `${Deno.cwd()}/dist`,
  `${Deno.cwd()}/public`,
]));

await app.listen({ port: 8000 });

Добавьте скрипт serve в ваш файл package.json для сборки приложения с помощью Vite и затем запуска сервера API:

{
  "scripts": {
    // ...
    "serve": "deno task build && deno task dev:api",
}

Теперь вы можете обслуживать собранное приложение с помощью Deno, выполнив:

deno task serve

Если вы посетите localhost:8000 в вашем браузере, вы должны увидеть запущенное приложение!

🦕 Теперь вы можете создать и разрабатывать приложение React с Vite и Deno! Вы готовы создать быстрые веб-приложения. Надеемся, вам понравится изучение этих передовых инструментов, мы с нетерпением ждём, что вы создадите!

© 2018–2024 the Deno authors
Licensed under the MIT License.
https://docs.deno.com/runtime/tutorials/how_to_with_npm/create-react

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API