nuckty
EN
Все разделы →

Ассеты: CSS и JS

Движок собирает CSS и JS в бандлы по зависимостям блоков. Имя каждого бандла включает content-hash, поэтому файлы могут храниться в кэше длительное время. Манифест хранит размеры и хэши — его использует команда публикации.

Файлы из внешних репозиториев

Стадия assets копирует файлы PDF, ZIP и INI из объявленных внешних репозиториев в корень артефакта, сохраняя имя файла. Если найдено несколько файлов с одинаковым именем, сборка завершается ошибкой. Чтобы явно выбрать источник, задайте в config/site.json поле assetSources: укажите имя файла в артефакте и точный путь к источнику относительно корня проекта-потребителя:

{
    "assetSources": {
        "manual.pdf": "external/docs/manual.pdf"
    }
}

По этому пути должен находиться кандидат с указанным именем. Если файл отсутствует или путь не совпадает с найденным источником, сборка завершится ошибкой. Для уникальных имён настройка не нужна. Для MP4 действуют те же правила коллизий и assetSources, но в выходное имя входит хэш, рассчитанный поточным чтением файла.

Бандлы по зависимостям

Бандл собирает стили и скрипты блоков из своей декларации; автоматически по содержимому страницы он не формируется. Если блок входит в зависимости, его block.css и block.js попадают в бандл. Блоки вне декларации не включаются.

Имя бандла берётся из site.json → bundles. Например, при "bundles": ["docs-layout"] движок читает docs-layout.bemdecl.js и собирает по этой декларации бандл docs-layout.

Стадии собирают все бандлы из site.json. Стандартный root подключает все переданные CSS и JS на каждой странице. Чтобы выбирать бандлы для отдельных страниц, задайте это в собственном обработчике документа или переопределённом шаблоне root.

CSS

Lightning CSS встраивает @import, расставляет префиксы, обрабатывает вложенные правила и минифицирует CSS. После этого собственный код стадии nuckty переписывает url() по .build/image-mapping.json и встраивает подходящие SVG.

Результат — файл <hash>.css в каталоге css/:

site/css/a1b2c3d4.css

Хэш в имени — content-hash: первые 16 шестнадцатеричных символов MD5 от содержимого файла (тот же алгоритм, что и в манифесте). Имя зависит от содержимого, поэтому файл можно хранить в кэше длительное время: при изменении меняется и хэш. В примерах на этой странице хэши сокращены для наглядности.

JS

esbuild собирает JS в формате IIFE, ориентируется на ES2018 и минифицирует код. Результат — файл <hash>.js в каталоге js/:

site/js/e5f6a7b8.js

Имя бандла JS также зависит от content-hash.

Переписывание ссылок на изображения

В CSS изображения подключают через url(...). При сборке движок переписывает эти ссылки по image-mapping.json: заменяет логический путь путём к файлу с хэшем в имени. Тот же image-mapping.json использует и мост Markdown, поэтому имена в CSS и в HTML всегда согласованы.

/* исходник */
.icon { background: url(images/icon.png); }

/* результат */
.icon{background:url(/_i9f8e7d6a1b2c3d4)}

manifest.json

Манифест хранит размеры и хэши файлов артефакта, кроме самого manifest.json. Сканирование выполняется после записи .htaccess. Его использует расширение публикации, чтобы сравнить манифест с файлами на сервере: загружается только то, что изменилось.

{
    "css/a1b2c3d4.css": { "size": 12450, "hash": "a1b2c3d4e5f6a7b8" },
    "js/e5f6a7b8.js":   { "size": 8920,  "hash": "e5f6a7b8c1d2e3f4" },
    "html/how_bemjson.html": { "size": 3200, "hash": "..." }
}

Хэш — первые 16 шестнадцатеричных символов MD5 от всего содержимого файла, в том числе крупных бинарных файлов ZIP и PDF. Ключи отсортированы, поэтому манифест детерминирован.

Неизменяемый кэш

Конфигурация задаёт файлам с хешем в имени длительный срок хранения (10 лет) и Cache-Control: public, immutable. HTML отдаётся с no-cache: его можно хранить, но перед повторным использованием требуется проверка актуальности. Подробнее — конфигурация хостинга.