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