Конфигурация хостинга
При сборке nuckty генерирует отдельную конфигурацию для каждого класса хостинга. Артефакт поддерживает локальный nginx и виртуальный хостинг Apache с FTP. Apache должен разрешать настройки через .htaccess и предоставлять необходимые модули rewrite, headers и mime. Почему так, объясняет решение о хостинге.
Два файла
| Файл | Куда попадает | Для какого хостинга |
|---|---|---|
nginx.conf | buildDir/ (не в outDir — для nginx) | nginx, VPS с nginx, CI |
.htaccess | outDir/ (публикуется с артефактом) | Виртуальный хостинг с Apache и mod_rewrite |
Оба файла собирает генератор конфигурации: он формирует строки напрямую, без шаблонизаторов вроде Nunjucks. Писать конфигурацию вручную не нужно.
При каждой сборке генерируется nginx.conf, даже если нужен только артефакт для Apache. Генератор nginx отклоняет файловые пути с символом доллара ($) и управляющими символами.
Что внутри
Конфигурация решает пять задач. nginx и Apache учитывают заголовки согласования форматов, каждый своим синтаксисом.
1. Выбор кодека сжатия
Сервер выбирает каталог с заранее сжатым файлом по заголовку Accept-Encoding — brotli/, затем gzip/. В nginx прямой доступ к этим каталогам закрыт. Сокращённый пример показывает только приоритет; сгенерированная map также исключает кодеки с нулевым качеством (q=0):
map $http_accept_encoding $compression_dir {
default "";
"~*\bbr\b" "brotli/";
"~*\bgzip\b" "gzip/";
}
Подробнее — сжатие.
2. Выбор формата изображения
Сервер отдаёт для одного адреса первый существующий формат по порядку: AVIF → WebP → оригинал:
location ~ ^/_i([a-f0-9]+)$ {
set $hash $1;
try_files $avif_dir/$hash.avif $webp_dir/$hash.webp /png/$hash.png /jpg/$hash.jpg /jpg/$hash.jpeg /svg/$hash.svg /$hash.gif /$hash.ico /webp/$hash.webp =404;
}
Оба сервера учитывают Accept: AVIF и WebP выбираются при явном разрешении формата с ненулевым q. В nginx это определяет значения $avif_dir и $webp_dir; в Apache — условия перезаписи. Затем сервер ищет оригинал. Если единственный оригинал — WebP, он доступен и без Accept. Ответы содержат Vary: Accept.
3. Плоские адреса
Движок хранит иерархический путь /how/bemjson на диске как how_bemjson.html. При запросе сервер преобразует путь в плоское имя файла:
# /a/b/c → a_b_c.html (при запросе, до 5 уровней)
Адрес остаётся чистым иерархическим, а файловая структура — плоской.
Адреса страниц не должны занимать техническое пространство: расширения статических файлов (html, css, js, svg, xml, jpg, jpeg, png, gif, ico, avif, webp, pdf, zip, ini, mp4), /brotli и /gzip с вложенными путями, старые /_c<hex>, /_j<hex>, /_s<hex>, /_i<hex>, /robots.txt, /manifest.json, /__nuckty_404, а также точные адреса каталогов артефакта /html, /css, /js, /svg, /xml, /png, /jpg, /webp, /avif. Сборка отклоняет их до записи страниц HTML. Другие адреса с точкой, например /release/1.0.0, поддерживаются. Упоминание .html в query не активирует ограничение Apache прямого доступа к файлам.
4. Кэширование
Ассеты с хешем в имени получают длительный срок хранения — 10 лет:
Cache-Control: public, immutable
Expires: +10 лет
HTML отдаётся с public, no-cache: кэш может его хранить, но перед повторным использованием должен проверить актуальность. Заголовок Vary: Accept-Encoding нужен, чтобы промежуточные кэши учитывали выбранный кодек.
5. Заголовки безопасности
Базовые заголовки безопасности в ответах с HTML:
X-Frame-Options: SAMEORIGINX-Content-Type-Options: nosniffReferrer-Policy: strict-origin-when-cross-origin
Ответы с собственной HTML-страницей ошибки 404 получают те же заголовки, в том числе при отдаче сжатого представления.
Эти заголовки включают отдельные защитные механизмы браузера; политику безопасности конкретного сайта задают отдельно.
Куда что попадает
site/ (outDir, публикуется)
├── html/, css/, js/, avif/, webp/, png/, jpg/, svg/
├── brotli/, gzip/
├── .htaccess ← едет с артефактом на виртуальный хостинг
└── manifest.json
.build/ (buildDir, служебный)
└── nginx.conf ← конфигурация nginx; для Apache не нужен
Apache читает .htaccess из outDir. nginx.conf находится отдельно в buildDir; расширение просмотра генерирует собственный .build/nginx-serve.conf и не использует автоматически хуки, изменившие файл сборки.
Публичный файл .txt, созданный расширением, отдаётся как text/plain; при наличии разрешённой копии сервер выбирает Brotli или Gzip. Для вложенного текстового файла используется плоское имя сжатой копии; коллизии имён прерывают сжатие. robots.txt остаётся несжатым. Если по адресу с точкой нет текстового артефакта, HTML-страница сохраняет обычную маршрутизацию.
Чего пока нет
Конфигурация решает технические задачи отдачи: согласование форматов, кэш, безопасность. Редиректы вида Redirect 301 /old /new в неё не входят — их добавляют через хук after стадий htaccess и nginx (см. pipeline-расширения). Это сделано намеренно: редиректы — задача сайта, а не движка.