Перейти к содержанию

Фронтенд

🌐 Перевод выполнен с помощью ИИ и людей

Этот перевод был сделан ИИ под руководством людей. 🤝

В нем могут быть ошибки из-за неправильного понимания оригинального смысла или неестественности и т. д. 🤖

Вы можете улучшить этот перевод, помогая нам лучше направлять ИИ LLM.

Английская версия

Вы можете «отдавать» статические фронтенд-приложения с помощью app.frontend() (или router.frontend()).

Это полезно для фронтенд-инструментов, которые генерируют статические файлы, таких как React с Vite, TanStack Router, Astro, Vue, Svelte, Angular, Solid и других.

С такими инструментами обычно есть этап сборки фронтенда с помощью команды вроде:

npm run build

Она сгенерирует директорию вроде ./dist/ с файлами вашего фронтенда.

Вы можете использовать app.frontend(), чтобы «отдавать» эту директорию, следуя соглашениям, которые требуются этим фронтенд-фреймворкам.

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

Отдача фронтенда

После сборки фронтенда, например с помощью npm run build, поместите сгенерированные файлы в директорию, например dist.

Структура вашего проекта может выглядеть так:

.
├── pyproject.toml
├── app
│   ├── __init__.py
│   └── main.py
└── dist
    ├── index.html
    └── assets
        └── app.js

Затем «отдавайте» её с помощью app.frontend():

from fastapi import FastAPI

app = FastAPI()

app.frontend("/", directory="dist")

При этом запрос к /assets/app.js может отдать dist/assets/app.js.

Если у вас также есть операция пути FastAPI, приоритет будет у операции пути.

Маршрутизация на стороне клиента

Многие фронтенд-приложения, включая single-page apps (SPA), используют маршрутизацию на стороне клиента. Путь вроде /dashboard/settings может не быть реальным файлом, но фреймворк возьмёт на себя его обработку.

Поэтому, если обратиться к этому URL напрямую (а не перейти к нему через приложение), backend должен отдать фронтенд-приложение из index.html, чтобы затем фронтенд-фреймворк мог обработать маршрутизацию на стороне клиента.

Для этого используйте fallback="index.html":

from fastapi import FastAPI

app = FastAPI()

app.frontend("/", directory="dist", fallback="index.html")

FastAPI использует этот fallback только для запросов GET и HEAD, которые похожи на навигацию в браузере. Отсутствующие файлы, такие как JavaScript, CSS и изображения, по-прежнему возвращают 404.

Запросы с другими методами, например POST или PUT, к путям, которые совпадают только с fallback фронтенда, также возвращают 404. Обычные операции пути FastAPI по-прежнему имеют более высокий приоритет, чем маршруты фронтенда.

Совет

По умолчанию fallback имеет значение fallback="auto". В большинстве случаев вам не нужно будет указывать fallback. Подробности ниже.

Именно такое поведение нужно для многих фронтенд-приложений, которые используют маршрутизацию на стороне клиента, например React с TanStack Router, Vue, Angular, SvelteKit или Solid.

Кастомная страница 404

Вы также можете отдавать статическую страницу 404.html для отсутствующих путей фронтенда:

from fastapi import FastAPI

app = FastAPI()

app.frontend("/", directory="dist", fallback="404.html")

Этот HTTP-ответ сохраняет статус-код 404.

В этом случае FastAPI не будет отдавать index.html для отсутствующих путей фронтенда. Вместо этого он вернёт файл 404.html.

Совет

По умолчанию fallback имеет значение fallback="auto". При этом, если найден файл 404.html, он будет автоматически использован как fallback.

Поэтому обычно можно не указывать аргумент fallback.

Это полезно с фронтенд-инструментами, которые генерируют статические HTML-файлы для каждой страницы, например Astro.

Автоматический fallback

По умолчанию app.frontend() использует fallback="auto".

Если в директории фронтенда есть файл 404.html, отсутствующие пути фронтенда отдают этот файл со статус-кодом 404.

В противном случае, если есть файл index.html, отсутствующие пути навигации в браузере отдают index.html, что и ожидают многие фронтенд-приложения с маршрутизацией на стороне клиента.

Поэтому в большинстве случаев можно использовать app.frontend("/", directory="dist") без указания аргумента fallback.

from fastapi import FastAPI

app = FastAPI()

app.frontend("/", directory="dist")

Отключение fallback

Если вы не хотите отдавать fallback-файл для отсутствующих путей фронтенда, используйте fallback=None:

from fastapi import FastAPI

app = FastAPI()

app.frontend("/", directory="dist", fallback=None)

Тогда отсутствующие пути фронтенда будут возвращать обычный 404.

Проверка директории

По умолчанию app.frontend() проверяет, что директория существует, при создании приложения.

Это помогает рано обнаруживать ошибки конфигурации. Например, если отсутствует директория с результатом сборки фронтенда, FastAPI вызовет ошибку при запуске.

Если ваши фронтенд-файлы создаются позже, например отдельным этапом сборки после создания объекта приложения, установите check_dir=False:

from fastapi import FastAPI

app = FastAPI()

app.frontend("/", directory="dist", check_dir=False)

С check_dir=False FastAPI не будет проверять директорию при создании приложения. Если настроенная директория всё ещё отсутствует во время обработки HTTP-запроса, FastAPI вызовет ошибку тогда.

Использование с APIRouter

Вы также можете добавить фронтенд-файлы в APIRouter и включить его с префиксом:

from fastapi import APIRouter, FastAPI

app = FastAPI()
router = APIRouter()

router.frontend("/", directory="dist", fallback="index.html")
app.include_router(router, prefix="/app")

В этом примере пути фронтенда отдаются под /app.

Любые обычные операции пути в приложении всё равно будут иметь приоритет, включая операции в других роутерах.

Только статический результат сборки

app.frontend() отдаёт файлы, уже сгенерированные сборкой вашего фронтенда.

Он не запускает server-side rendering. Он предназначен для фронтенд-фреймворков, которые генерируют статические файлы, а не для фреймворков, которым требуется динамический рендеринг на сервере для каждого HTTP-запроса.