Build Output Manifest
Build Output Manifest — JSON-файл .onreza/manifest.json, который описывает что нужно развернуть и где это должно работать. Это контракт между вашим проектом и платформой.
Платформа читает манифест и выполняет ровно то, что в нём написано:
- Статические файлы → CDN (мгновенная отдача, кэширование)
- Fetch-handlers → Edge Runtime (V8 isolate, быстрый cold start)
- Серверные процессы → Compute sandbox (полный Node.js/Bun)
Быстрый старт
Заголовок раздела «Быстрый старт»Vite / React / Vue SPA
Заголовок раздела «Vite / React / Vue SPA»Ничего делать не нужно. nrz deploy автоматически создаёт манифест для статических сайтов.
Astro / SvelteKit / Nuxt с SSR
Заголовок раздела «Astro / SvelteKit / Nuxt с SSR»nrz deploy определяет тип фреймворка и генерирует манифест автоматически. Никаких дополнительных пакетов устанавливать не нужно.
Next.js
Заголовок раздела «Next.js»nrz deploy создаёт два слоя: статические ассеты → CDN, серверный процесс → Compute.
Вручную
Заголовок раздела «Вручную»Создайте .onreza/manifest.json в output-директории вашего билда:
{ "version": 1, "layers": [ { "name": "site", "target": "STATIC", "directory": "." } ], "routes": [ { "pattern": "^/.*$", "layer": "site" } ]}Основные концепции
Заголовок раздела «Основные концепции»Layers (слои)
Заголовок раздела «Layers (слои)»Слой — это набор файлов с указанием, где их запускать:
| Target | Что это | Когда использовать |
|---|---|---|
STATIC | CDN-раздача файлов | HTML, CSS, JS, изображения, шрифты |
ISOLATE | V8 Runtime (edge) | SSR, API endpoints, ISR — лёгкий, быстрый cold start |
COMPUTE | Полный серверный процесс | Next.js standalone, Express, Fastify — полный Node.js/Bun |
Один деплой может содержать несколько слоёв. Статика раздаётся через CDN бесплатно и мгновенно, а compute-ресурсы тратятся только на динамические запросы.
Routes (маршруты)
Заголовок раздела «Routes (маршруты)»Маршруты определяют, какой слой отвечает на какой URL:
{ "routes": [ { "pattern": "^/_next/static/.*$", "layer": "static", "priority": 100 }, { "pattern": "^/api/.*$", "layer": "server", "priority": 20 }, { "pattern": "^/.*$", "layer": "server", "priority": 0 } ]}Как работает:
- Маршруты сортируются по
priority(больше = проверяется раньше) - Первый regex-match побеждает
- Запрос отправляется в слой, указанный в
layer
Приоритеты
Заголовок раздела «Приоритеты»| Тип маршрута | Priority |
|---|---|
Hashed assets (/_next/static/) | 100 |
| Конкретные статические страницы | 50 |
| ISR страницы | 30 |
| API routes | 20 |
| Catch-all (серверный fallback) | 0 |
Поле priority опционально (default: 0), но рекомендуется указывать явно при наличии нескольких маршрутов.
Примеры
Заголовок раздела «Примеры»{ "version": 1, "layers": [ { "name": "site", "target": "STATIC", "directory": "dist" } ], "routes": [ { "pattern": "^/.*$", "layer": "site", "priority": 0 } ]}{ "version": 1, "layers": [ { "name": "assets", "target": "STATIC", "directory": "client" }, { "name": "server", "target": "ISOLATE", "directory": "server", "entry": "entry.mjs", "export": "fetch" } ], "routes": [ { "pattern": "^/_astro/.*$", "layer": "assets", "priority": 100 }, { "pattern": "^/api/.*$", "layer": "server", "priority": 20, "methods": ["GET", "POST"] }, { "pattern": "^/.*$", "layer": "server", "priority": 0 } ]}{ "version": 1, "layers": [ { "name": "static", "target": "STATIC", "directory": "static" }, { "name": "server", "target": "COMPUTE", "directory": "standalone", "entry": "server.js", "runtime": { "memoryMb": 512 } } ], "routes": [ { "pattern": "^/_next/static/.*$", "layer": "static", "priority": 100 }, { "pattern": "^/.*$", "layer": "server", "priority": 0 } ]}Без статического слоя каждый запрос к style.css проходит через серверный процесс, тратя compute-ресурсы. С двумя слоями статика раздаётся через CDN за микросекунды.
{ "routes": [ { "pattern": "^/blog/.*$", "layer": "server", "priority": 30, "revalidate": 60 } ]}revalidate: 60 — отдавать кэшированную версию, обновлять в фоне каждые 60 секунд. Максимум: 31 536 000 секунд (1 год).
{ "layers": [ { "name": "prerendered", "target": "STATIC", "directory": "prerender" }, { "name": "server", "target": "ISOLATE", "directory": "server", "entry": "entry.mjs", "export": "fetch" } ], "routes": [ { "pattern": "^/about/?$", "layer": "prerendered", "priority": 50 }, { "pattern": "^/.*$", "layer": "server", "priority": 0 } ], "prerender": { "layer": "prerendered", "pages": { "/about": { "html": "about/index.html" } } }}Поля слоя
Заголовок раздела «Поля слоя»| Поле | Тип | Обязательно | Описание |
|---|---|---|---|
name | string | да | Уникальное имя слоя (до 64 символов) |
target | "STATIC" | да | Тип слоя |
directory | string | да | Директория с файлами относительно output-директории |
ISOLATE
Заголовок раздела «ISOLATE»| Поле | Тип | Обязательно | Описание |
|---|---|---|---|
name | string | да | Уникальное имя слоя |
target | "ISOLATE" | да | Тип слоя |
directory | string | да | Директория с файлами бандла |
entry | string | да | Путь к entry файлу внутри directory |
export | string | нет | Экспортируемый символ (default: "default") |
runtime | object | нет | Настройки ресурсов |
COMPUTE
Заголовок раздела «COMPUTE»| Поле | Тип | Обязательно | Описание |
|---|---|---|---|
name | string | да | Уникальное имя слоя |
target | "COMPUTE" | да | Тип слоя |
directory | string | да | Директория с серверным процессом |
entry | string | да | Путь к entry файлу |
runtime | object | нет | Настройки ресурсов |
Поля маршрута
Заголовок раздела «Поля маршрута»| Поле | Тип | Обязательно | Описание |
|---|---|---|---|
pattern | string | да | Regex-паттерн для URL (Rust regex синтаксис) |
layer | string | да | Имя слоя из layers |
priority | number | нет | Приоритет (default: 0, больше = раньше) |
methods | string[] | нет | HTTP методы: GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS |
revalidate | number | нет | Время кэша в секундах (ISR). Только для ISOLATE/COMPUTE слоёв |
fallthrough | boolean | нет | При 404 перейти к следующему маршруту. Default: true для STATIC, false для остальных |
Fallthrough
Заголовок раздела «Fallthrough»Когда STATIC-маршрут с fallthrough: true (default для всех STATIC) не находит файл в хранилище, запрос переходит к следующему подходящему маршруту вместо 404.
{ "routes": [ { "pattern": "^/.*\\..*$", "layer": "static", "priority": 50 }, { "pattern": "^/.*$", "layer": "server", "priority": 0 } ]}GET /favicon.ico→ паттерн^/.*\\..*$совпал → STATIC (файл есть) → CDNGET /style.css→ паттерн^/.*\\..*$совпал → STATIC (файл есть) → CDNGET /unknown.js→ паттерн^/.*\\..*$совпал → STATIC (файла нет, fallthrough) →^/.*$→ server → SSRGET /about→ паттерн^/.*\\..*$не совпал (нет расширения) →^/.*$→ server → SSR напрямую
ISOLATE vs COMPUTE
Заголовок раздела «ISOLATE vs COMPUTE»| ISOLATE | COMPUTE | |
|---|---|---|
| Runtime | V8 isolate | Полный Bun / Node.js |
| Cold start | ~5ms (warm) | ~500ms–2s |
| Handler | fetch(Request): Response | Произвольный HTTP сервер |
| Файловая система | Нет | Read-only (кроме /tmp) |
| WebSocket | Нет | Да |
| Native modules | Нет | Да |
| Подходит для | Astro SSR, SvelteKit, API handlers | Next.js standalone, Express, Fastify |
Правило: если ваш фреймворк умеет экспортировать fetch handler — используйте ISOLATE. Если нужен полный серверный процесс — COMPUTE.
Runtime configuration
Заголовок раздела «Runtime configuration»Для ISOLATE и COMPUTE слоёв можно задать лимиты ресурсов в поле runtime:
{ "name": "server", "target": "COMPUTE", "directory": "standalone", "entry": "server.js", "runtime": { "timeoutMs": 60000, "memoryMb": 512 }}| Параметр | ISOLATE default | COMPUTE default | Описание |
|---|---|---|---|
timeoutMs | 30 000 (30s) | 300 000 (5 мин) | Таймаут выполнения |
memoryMb | 128 | 256 | Лимит памяти |
maxConcurrency | 10 | — | Макс. параллельных выполнений (только ISOLATE) |
Middleware
Заголовок раздела «Middleware»Middleware — перехватчики запросов, которые выполняются до маршрутизации:
{ "middleware": [ { "name": "auth", "bundlePath": "middleware/auth.mjs", "codeHash": "sha256-abc123", "matchers": ["^/(?:api|dashboard)/.*$"], "priority": 10 } ]}| Поле | Описание |
|---|---|
name | Уникальное имя |
bundlePath | Путь к файлу middleware |
codeHash | SHA-256 хэш файла |
matchers | Список regex-паттернов для URL (Rust regex синтаксис) |
priority | Порядок выполнения (выше = раньше, default: 0) |
Meta (метаданные)
Заголовок раздела «Meta (метаданные)»Необязательные метаданные для dashboard и отладки:
{ "meta": { "framework": { "name": "astro", "version": "5.2.0" } }}Платформа показывает их в dashboard: «Deployed with Astro 5.2.0». Можно добавить любые поля — платформа сохраняет, но не валидирует содержимое. Максимальный размер: 16 KB.
Ошибки валидации
Заголовок раздела «Ошибки валидации»Если манифест невалиден, деплой отклоняется с понятным сообщением:
Manifest validation failed:
layers[1].entry: Entry not found: "server/entry.mjs" routes[2].layer: Route references unknown layer: "cdn"
See: docs.onreza.ru/manifestRegex ограничения
Заголовок раздела «Regex ограничения»Паттерны маршрутов и matchers middleware используют синтаксис Rust regex crate. Следующие JavaScript-специфичные фичи не поддерживаются и вызовут ошибку валидации:
- Lookahead / lookbehind:
(?=...),(?!...),(?<=...),(?<!...) - Backreferences:
\1,\2и т.д. - Atomic groups:
(?>...)
Используйте явные альтернативы. Например, вместо ^/((?!_next/static).*)$ используйте два маршрута с разными приоритетами.
| Параметр | Лимит |
|---|---|
| Слоёв на деплой | 10 |
| Маршрутов на деплой | 200 |
| Middleware на деплой | 10 |
| Длина паттерна | 500 символов |
Длина name слоя | 64 символа |
Длина directory | 256 символов |
Длина entry | 512 символов |
Размер meta (JSON) | 16 KB |
Pattern cheatsheet
Заголовок раздела «Pattern cheatsheet»| Задача | Pattern |
|---|---|
| Точный путь | ^/about$ |
| С trailing slash | ^/about/?$ |
| Dynamic segment | ^/blog/[^/]+$ |
| Wildcard | ^/api/.*$ |
| Catch-all | ^/.*$ |
| Hashed assets | ^/_next/static/.*$ |
| Multiple segments | ^/blog/[^/]+/comments$ |
См. также
Заголовок раздела «См. также»- Edge Runtime — API для ISOLATE слоёв
- Middleware — перехватчики запросов