Browse Source
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Yurii Motov <[email protected]>pull/15903/head
committed by
GitHub
1 changed files with 133 additions and 0 deletions
@ -0,0 +1,133 @@ |
|||||
|
# Фронтенд { #frontend } |
||||
|
|
||||
|
Вы можете «отдавать» статические фронтенд-приложения с помощью `app.frontend()` (или `router.frontend()`). |
||||
|
|
||||
|
Это полезно для фронтенд-инструментов, которые генерируют статические файлы, таких как React с Vite, TanStack Router, Astro, Vue, Svelte, Angular, Solid и других. |
||||
|
|
||||
|
С такими инструментами обычно есть этап сборки фронтенда с помощью команды вроде: |
||||
|
|
||||
|
```bash |
||||
|
npm run build |
||||
|
``` |
||||
|
|
||||
|
Она сгенерирует директорию вроде `./dist/` с файлами вашего фронтенда. |
||||
|
|
||||
|
Вы можете использовать `app.frontend()`, чтобы «отдавать» эту директорию, следуя соглашениям, которые требуются этим фронтенд-фреймворкам. |
||||
|
|
||||
|
**FastAPI** сначала проверяет *операции пути*. Файлы фронтенда проверяются только если не совпал ни один обычный маршрут, поэтому ваш API не будет затронут. |
||||
|
|
||||
|
## Отдача фронтенда { #serve-a-frontend } |
||||
|
|
||||
|
После сборки фронтенда, например с помощью `npm run build`, поместите сгенерированные файлы в директорию, например `dist`. |
||||
|
|
||||
|
Структура вашего проекта может выглядеть так: |
||||
|
|
||||
|
```text |
||||
|
. |
||||
|
├── pyproject.toml |
||||
|
├── app |
||||
|
│ ├── __init__.py |
||||
|
│ └── main.py |
||||
|
└── dist |
||||
|
├── index.html |
||||
|
└── assets |
||||
|
└── app.js |
||||
|
``` |
||||
|
|
||||
|
Затем «отдавайте» её с помощью `app.frontend()`: |
||||
|
|
||||
|
{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} |
||||
|
|
||||
|
При этом запрос к `/assets/app.js` может отдать `dist/assets/app.js`. |
||||
|
|
||||
|
Если у вас также есть *операция пути* **FastAPI**, приоритет будет у *операции пути*. |
||||
|
|
||||
|
## Маршрутизация на стороне клиента { #client-side-routing } |
||||
|
|
||||
|
Многие фронтенд-приложения, включая **single-page apps** (SPA), используют маршрутизацию на стороне клиента. Путь вроде `/dashboard/settings` может не быть реальным файлом, но фреймворк возьмёт на себя его обработку. |
||||
|
|
||||
|
Поэтому, если обратиться к этому URL напрямую (а не перейти к нему через приложение), backend должен отдать фронтенд-приложение из `index.html`, чтобы затем фронтенд-фреймворк мог обработать маршрутизацию на стороне клиента. |
||||
|
|
||||
|
Для этого используйте `fallback="index.html"`: |
||||
|
|
||||
|
{* ../../docs_src/frontend/tutorial002_py310.py hl[5] *} |
||||
|
|
||||
|
**FastAPI** использует этот fallback только для запросов `GET` и `HEAD`, которые похожи на навигацию в браузере. Отсутствующие файлы, такие как JavaScript, CSS и изображения, по-прежнему возвращают `404`. |
||||
|
|
||||
|
Запросы с другими методами, например `POST` или `PUT`, к путям, которые совпадают только с fallback фронтенда, также возвращают `404`. Обычные *операции пути* **FastAPI** по-прежнему имеют более высокий приоритет, чем маршруты фронтенда. |
||||
|
|
||||
|
/// tip | Совет |
||||
|
|
||||
|
По умолчанию `fallback` имеет значение `fallback="auto"`. В большинстве случаев вам не нужно будет указывать `fallback`. Подробности ниже. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
Именно такое поведение нужно для многих фронтенд-приложений, которые используют маршрутизацию на стороне клиента, например React с TanStack Router, Vue, Angular, SvelteKit или Solid. |
||||
|
|
||||
|
## Кастомная страница 404 { #custom-404-page } |
||||
|
|
||||
|
Вы также можете отдавать статическую страницу `404.html` для отсутствующих путей фронтенда: |
||||
|
|
||||
|
{* ../../docs_src/frontend/tutorial003_py310.py hl[5] *} |
||||
|
|
||||
|
Этот HTTP-ответ сохраняет статус-код `404`. |
||||
|
|
||||
|
В этом случае **FastAPI** не будет отдавать `index.html` для отсутствующих путей фронтенда. Вместо этого он вернёт файл `404.html`. |
||||
|
|
||||
|
/// tip | Совет |
||||
|
|
||||
|
По умолчанию `fallback` имеет значение `fallback="auto"`. При этом, если найден файл `404.html`, он будет автоматически использован как fallback. |
||||
|
|
||||
|
Поэтому обычно можно не указывать аргумент `fallback`. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
Это полезно с фронтенд-инструментами, которые генерируют статические HTML-файлы для каждой страницы, например Astro. |
||||
|
|
||||
|
## Автоматический fallback { #fallback-auto } |
||||
|
|
||||
|
По умолчанию `app.frontend()` использует `fallback="auto"`. |
||||
|
|
||||
|
Если в директории фронтенда есть файл `404.html`, отсутствующие пути фронтенда отдают этот файл со статус-кодом `404`. |
||||
|
|
||||
|
В противном случае, если есть файл `index.html`, отсутствующие пути навигации в браузере отдают `index.html`, что и ожидают многие фронтенд-приложения с маршрутизацией на стороне клиента. |
||||
|
|
||||
|
Поэтому в большинстве случаев можно использовать `app.frontend("/", directory="dist")` без указания аргумента `fallback`. |
||||
|
|
||||
|
{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} |
||||
|
|
||||
|
## Отключение fallback { #disable-fallback } |
||||
|
|
||||
|
Если вы не хотите отдавать fallback-файл для отсутствующих путей фронтенда, используйте `fallback=None`: |
||||
|
|
||||
|
{* ../../docs_src/frontend/tutorial005_py310.py hl[5] *} |
||||
|
|
||||
|
Тогда отсутствующие пути фронтенда будут возвращать обычный `404`. |
||||
|
|
||||
|
## Проверка директории { #check-directory } |
||||
|
|
||||
|
По умолчанию `app.frontend()` проверяет, что директория существует, при создании приложения. |
||||
|
|
||||
|
Это помогает рано обнаруживать ошибки конфигурации. Например, если отсутствует директория с результатом сборки фронтенда, **FastAPI** вызовет ошибку при запуске. |
||||
|
|
||||
|
Если ваши фронтенд-файлы создаются позже, например отдельным этапом сборки после создания объекта приложения, установите `check_dir=False`: |
||||
|
|
||||
|
{* ../../docs_src/frontend/tutorial006_py310.py hl[5] *} |
||||
|
|
||||
|
С `check_dir=False` **FastAPI** не будет проверять директорию при создании приложения. Если настроенная директория всё ещё отсутствует во время обработки HTTP-запроса, **FastAPI** вызовет ошибку тогда. |
||||
|
|
||||
|
## Использование с `APIRouter` { #use-it-with-apirouter } |
||||
|
|
||||
|
Вы также можете добавить фронтенд-файлы в `APIRouter` и включить его с префиксом: |
||||
|
|
||||
|
{* ../../docs_src/frontend/tutorial004_py310.py hl[6,7] *} |
||||
|
|
||||
|
В этом примере пути фронтенда отдаются под `/app`. |
||||
|
|
||||
|
Любые обычные *операции пути* в приложении всё равно будут иметь приоритет, включая операции в других роутерах. |
||||
|
|
||||
|
## Только статический результат сборки { #static-build-output-only } |
||||
|
|
||||
|
`app.frontend()` отдаёт файлы, уже сгенерированные сборкой вашего фронтенда. |
||||
|
|
||||
|
Он не запускает server-side rendering. Он предназначен для фронтенд-фреймворков, которые генерируют статические файлы, а не для фреймворков, которым требуется динамический рендеринг на сервере для каждого HTTP-запроса. |
||||
Loading…
Reference in new issue