diff --git a/docs/ru/docs/tutorial/frontend.md b/docs/ru/docs/tutorial/frontend.md new file mode 100644 index 0000000000..3b3e438094 --- /dev/null +++ b/docs/ru/docs/tutorial/frontend.md @@ -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-запроса.