Развёртывание
На этой странице
Сборка sitelo — это обычные статические файлы: sitelo build записывает HTML, CSS и JS в dist/. Подойдёт любой статический хостинг — конфигурации ниже предполагают лишь npm run build → dist/.
Чистые URL — это каталоги с index.html (/about/index.html → /about), так что красивые адреса работают сразу, без правил перенаправления. Файл 404.html создаётся автоматически — это соглашение понимают и Netlify, и Cloudflare Pages, и GitHub Pages.
Готовые к копированию версии всего этого лежат в базовом примере (examples/basic в репозитории).
Статические хостинги
Эти хостинги собирают сайт и раздают dist/ через собственную CDN.
Netlify · Vercel · Cloudflare · AWS Amplify · AWS S3 + CloudFront · Azure Static Web Apps · Firebase Hosting · GitHub Pages · GitLab Pages · Render · DigitalOcean App Platform
Netlify
[build]
command = "npm run build"
publish = "dist"Vercel
{
"$schema": "https://openapi.vercel.sh/vercel.json",
"framework": null,
"buildCommand": "npm run build",
"outputDirectory": "dist",
"installCommand": "npm install"
}Cloudflare
Для новых проектов Cloudflare теперь рекомендует Workers вместо Pages. С этой конфигурацией npx wrangler deploy собирает сайт и загружает dist/, а если подключить репозиторий в панели Cloudflare, та же команда выполняется при каждом push. html_handling: "drop-trailing-slash" отдаёт /about без перенаправления, а неизвестные URL получают 404.html.
// Cloudflare Workers
{
"name": "my-site",
"compatibility_date": "2026-10-01",
"build": {
"command": "npm run build"
},
"assets": {
"directory": "./dist",
"not_found_handling": "404-page",
"html_handling": "drop-trailing-slash"
}
}Остаётесь на Pages? Укажите команду сборки npm run build и каталог вывода dist или загрузите локальную сборку командой npx wrangler pages deploy dist.
AWS Amplify
# Хостинг AWS Amplify
version: 1
frontend:
phases:
preBuild:
commands:
- npm install
build:
commands:
- npm run build
artifacts:
baseDirectory: dist
files:
- '**/*'
cache:
paths:
- node_modules/**/*AWS S3 + CloudFront
Оставьте бакет закрытым и поставьте перед ним CloudFront с origin access control. CloudFront сопоставляет с index.html только /, поэтому привяжите эту функцию к viewer-запросам дистрибуции, чтобы работали чистые URL sitelo.
function handler(event) {
var request = event.request
var uri = request.uri
if (uri.endsWith('/')) {
request.uri += 'index.html'
} else if (uri.slice(uri.lastIndexOf('/') + 1).indexOf('.') === -1) {
request.uri += '/index.html'
}
return request
}Закрытый бакет отвечает на отсутствующий файл кодом 403, поэтому добавьте пользовательские ответы на ошибки 403 и 404, которые возвращают /404.html со статусом 404. Затем загружайте каждую сборку и сбрасывайте кэш:
npm run build
aws s3 sync dist/ s3://my-bucket --delete
aws cloudfront create-invalidation --distribution-id MY_DISTRIBUTION_ID --paths "/*"Azure Static Web Apps
Создайте Static Web App в портале Azure с расположением приложения / и расположением вывода dist — Azure добавит в репозиторий workflow GitHub Actions, который запускает npm run build. Положите этот файл в public/, чтобы сборка скопировала его в dist/: без него Azure отвечает на неизвестные URL своей страницей ошибки вместо 404.html.
{
"responseOverrides": {
"404": {
"rewrite": "/404.html"
}
}
}Firebase Hosting
В Firebase Hosting выберите проект командой firebase use --add, затем выполните firebase deploy — хук predeploy сначала соберёт сайт. Неизвестные URL автоматически получают 404.html, а trailingSlash: false отдаёт /about без перенаправления.
{
"hosting": {
"public": "dist",
"predeploy": "npm run build",
"trailingSlash": false
}
}GitHub Pages
# GitHub Pages
name: Deploy
on:
push:
branches: [main]
permissions:
contents: read
pages: write
id-token: write
jobs:
deploy:
runs-on: ubuntu-latest
environment:
name: github-pages
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
with:
node-version: 24
- run: npm ci && npm run build
- uses: actions/upload-pages-artifact@v5
with:
path: dist
- uses: actions/deploy-pages@v5Разворачиваете по подпути (user.github.io/repo)? Собирайте с --base /repo/.
GitLab Pages
GitLab сам отдаёт 404.html и URL каталогов, поэтому задача только собирает и публикует dist/.
# GitLab Pages
deploy-pages:
image: node:24
script:
- npm ci
- npm run build
pages:
publish: dist
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCHRender
Добавьте Blueprint ниже в репозиторий или создайте статический сайт в панели с той же командой сборки и каталогом публикации. Чистые URL и 404.html работают без правил перенаправления.
# Render
services:
- type: web
name: my-site
runtime: static
buildCommand: npm install && npm run build
staticPublishPath: ./distDigitalOcean App Platform
Укажите свой репозиторий в github.repo, затем создайте приложение командой doctl apps create --spec .do/app.yaml — или вставьте спецификацию в панели. App Platform по умолчанию разрешает URL каталогов и отдаёт 404.html.
# DigitalOcean App Platform
name: my-site
static_sites:
- name: site
github:
repo: your-name/your-site
branch: main
deploy_on_push: true
build_command: npm run build
output_dir: distКонтейнерные хостинги
Эти хостинги запускают контейнер, и одного Dockerfile хватает для всех: Node собирает сайт, затем Caddy раздаёт dist/ с чистыми URL и отвечает на неизвестные страницей 404.html. Caddy слушает PORT, если хостинг его задаёт, а иначе порт 80. Положите все три файла в корень проекта.
Railway · Fly.io · Heroku · Google Cloud Run
FROM node:24-slim AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM caddy:2-alpine
COPY Caddyfile /etc/caddy/Caddyfile
COPY --from=build /app/dist /app/distnode_modules
dist
.git:{$PORT:80} {
root * /app/dist
encode zstd gzip
try_files {path} {path}/index.html
file_server
handle_errors {
rewrite * /{err.status_code}.html
file_server
}
}Railway
Railway собирает Dockerfile, как только находит его, так что настраивать ничего не нужно. Без Dockerfile добавьте переменную сервиса RAILPACK_SPA_OUTPUT_DIR=dist и оставьте Caddyfile: тогда Railpack раздаёт dist/ через него, а не через свою стандартную SPA-настройку, которая отвечает на неизвестные URL главной страницей.
Fly.io
Создайте приложение командой fly launch, затем выполните fly deploy.
# Fly.io
app = "my-site"
[http_service]
internal_port = 80
force_https = true
auto_stop_machines = "stop"
auto_start_machines = true
min_machines_running = 0Heroku
Heroku собирает Dockerfile через heroku.yml. Один раз переключите приложение на контейнерный стек командой heroku stack:set container, затем выполните git push heroku main.
# Heroku
build:
docker:
web: DockerfileGoogle Cloud Run
Выполните gcloud run deploy --source . в корне проекта: Cloud Build соберёт Dockerfile, а Cloud Run будет его обслуживать.
Свой сервер
Скопируйте сборку на сервер командой rsync -a --delete dist/ you@server:/var/www/my-site/ и раздавайте её через Caddy или nginx — чистые URL и 404.html работают так же, как на хостингах выше. Caddy сам получает HTTPS-сертификат для домена; с nginx добавьте его через certbot.
example.com {
root * /var/www/my-site
encode zstd gzip
try_files {path} {path}/index.html
file_server
handle_errors {
rewrite * /{err.status_code}.html
file_server
}
}server {
listen 80;
server_name example.com;
root /var/www/my-site;
location / {
try_files $uri $uri/index.html =404;
}
error_page 404 /404.html;
}Перед публикацией
- Задайте
siteвsitelo.config.js, чтобы создавалсяsitemap.xml— см. Конфигурацию - Добавьте
src/404.ht.jsдля собственной страницы «не найдено» (иначе создаётся аккуратная страница по умолчанию) sitelo previewлокально отдаёт продакшн-сборку для финальной проверки