Витрина обычно тянет десятки мелких .js и
.css: библиотеки оформления, стили, скрипты отдельных
модулей. Каждый файл — отдельный запрос к серверу. Бандл склеивает их в
один файл, и происходит это прямо при сохранении в среде разработки —
без внешних сборщиков, конфигов и отдельной команды сборки.
Откройте .js или .css в среде разработки.
Над редактором две строки: синяя — описание файла, серая — параметры. В
параметрах указывается, в какие бандлы попадёт этот файл:
base.js: 4
Слева от двоеточия — имя бандла, справа — приоритет. Один файл может входить в несколько бандлов, они перечисляются через запятую:
base.js: 4, print.css: 2
Приоритет необязателен: без него файл получает 0. Имя
бандла становится именем итогового файла, поэтому расширение указывается
прямо в нём — base.js, melbis.css,
melbis.auth.js. В имени допустимы латинские буквы, цифры,
точка и подчёркивание; остальные символы вырезаются — в частности дефис,
так что melbis-auth.js превратится в
melbisauth.js.
В бандл попадает любой .js или .css внутри
группы шаблонов — и из общего каталога statics/, и
из каталогов отдельных модулей:
templates/default/
statics/
base/bootstrap.js base.js: 2
base/bootbox.js base.js: 4
melbis/main.js melbis.js: 1
units/
melbis_cataloge/scripts.js melbis.js: 10
melbis_base_page/scripts.js melbis.js: 15
В этом и смысл: модуль держит свой скрипт рядом со своими шаблонами, где его удобно править и искать, а на витрину код приезжает в общем файле, не добавляя запросов.
Собранный файл кладётся в statics/ той же группы
шаблонов, с префиксом bundle.:
templates/default/statics/bundle.melbis.js
Пересборка запускается при каждом сохранении файла, у которого заполнена строка бандлов, и пересобирает все бандлы группы целиком.
В начало файла дописывается отчёт о составе:
/* Melbis Shop auto bundle report */
/* Create: 2026-07-17 15:39:56 */
/* #1 main.js 32 ln 1 kb /templates/default/statics/melbis/main.js */
/* #10 scripts.js 57 ln 1 kb /templates/default/units/melbis_cataloge/scripts.js */
/* #15 scripts.js 77 ln 3 kb /templates/default/units/melbis_base_page/scripts.js */
По нему видно, что и в каком порядке вошло, — это первое, куда стоит заглянуть, когда непонятно, чей код отработал раньше.
Сборка — это только склейка. Минификации, транспиляции и переписывания путей внутри CSS не происходит: файлы соединяются в порядке приоритета как есть. Если нужен минифицированный вендорный код, кладите в бандл уже минифицированную версию файла.
Файлы сортируются по возрастанию приоритета. Сами числа условные — значение имеют только их отношения, поэтому удобно оставлять зазоры, чтобы потом вставлять файлы между уже существующими.
Приоритетами удобно разделять логические группы. Например, в
демонстрационном магазине до 10 идут базовые файлы из
statics/, после 10 — скрипты модулей: так библиотеки
заведомо загрузятся раньше кода, который на них опирается. Это не
правило платформы, а просто способ навести порядок.
Не оставляйте одинаковый приоритет файлам, порядок которых важен. Сортировка идёт только по числу, а файлы с равными значениями встают в том порядке, в каком движок обошёл каталог метаданных, — предсказать его нельзя.
<link rel="stylesheet" type="text/css" href="{PATH}/statics/bundle.base.css">
<link rel="stylesheet" type="text/css" href="{PATH}/statics/bundle.melbis.css?{BUILD}">
<script defer src="{PATH}/statics/bundle.base.js"></script>
<script defer src="{PATH}/statics/bundle.melbis.js?{BUILD}"></script>{BUILD} — номер сборки проекта, системный тег, доступный
в любом шаблоне. Он работает меткой версии: пока номер не изменился,
браузер берёт файл из своего кеша, а как только номер вырос — скачивает
заново.
Меняется он двумя способами: вручную — параметром
MELBIS_BUILD в диалоге «Проектирование →
Инсталляция» (см. «Конфигурация»), либо автоматически — кнопкой
в среде разработки, которая включает инкремент MELBIS_BUILD
при каждом сохранении файла.
Ставить ?{BUILD} можно у любого бандла. Вендорные
библиотеки меняются редко, поэтому их часто подключают без метки, — но
это дело вкуса, а не требование.
Чтобы убрать файл из бандла, сотрите имя бандла из строки параметров и сохраните файл: при ближайшей сборке он из бандла исчезнет.
Если из бандла ушёл последний файл, сам бандл остаётся на диске. Собирать его больше не из чего, поэтому движок его просто не трогает — прежний
statics/bundle.имяпродолжает лежать и отдаваться витрине. То же самое при переименовании бандла: появится файл с новым именем, а старый останется. Такие файлы удаляются вручную.
Удалять и переименовывать саму статику лучше в дереве среды
разработки: тогда метаданные о бандлах переносятся или снимаются вместе
с файлом. Если удалить файл мимо IDE — например, по FTP, — метаданные о
нём останутся, и очередная сборка сообщит об ошибке
Can't include file to bundle.
Бандл только склеивает. Если код нужно ещё и минифицировать,
обфусцировать или как-то иначе преобразовать, для этого есть отдельный
механизм — преобразователь файлов, Ctrl+B
или кнопка на панели редактирования.
Работает он так: среда отправляет на сервер имя файла и текущее содержимое редактора — вместе с несохранёнными правками, — сервер вызывает по HTTP ваш скрипт-преобразователь, а то, что тот вернёт, целиком заменяет текст в редакторе. Сам результат никуда не сохраняется: посмотрите, что получилось, и сохраните файл обычным способом.
Адрес скрипта задаётся в «Настройки редактора → Оптимизация → Преобразователь файлов»:
http://localhost/minify.php.Ctrl+B случайно
легко.Это настройка среды разработки, а не проекта: она не лежит в
config.json, и каждый разработчик задаёт её у себя.
Скрипт вызывает сервер, а не программа, — как и задачи планировщика. Поэтому в адресе стоит
localhost: сервер обращается сам к себе, и преобразователь работает сразу, без настройки домена. Если вынести скрипт на отдельный хост, адрес должен быть доступен с веб-сервера магазина, а не с рабочей станции.
Обычный POST с двумя полями:
| Поле | Что в нём |
|---|---|
name |
имя файла — по расширению удобно решать, что с ним делать |
content |
текущее содержимое редактора |
Вернуть нужно готовый текст в теле ответа — без обёрток, заголовков и
JSON. Ответ с кодом 400 и выше среда покажет как ошибку, а
содержимое редактора не тронет.
В демонстрационном магазине лежит готовый преобразователь — минификатор JS и CSS. Это обычный PHP-файл в корне проекта, движок в нём не участвует.
Начинается он с проверки, что запрос пришёл с самого сервера:
// Преобразователь вызывает движок, поэтому пускаем только локальные запросы
$ip = $_SERVER['REMOTE_ADDR'] ?? '';
if ( $ip !== '127.0.0.1' && $ip !== '::1' )
{
header('HTTP/1.1 403 Forbidden');
die('Only local allowed');
}Дальше — собственно преобразование:
switch ( pathinfo($_POST['name'], PATHINFO_EXTENSION) )
{
case 'js':
$data = array('input' => $_POST['content']);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://www.toptal.com/developers/javascript-minifier/api/raw');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 60);
echo curl_exec($ch);
curl_close($ch);
break;
case 'css':
// То же самое, но обращение к минификатору CSS
break;
default:
echo $_POST['content'];
}Разбор по расширению — не требование платформы, а удобное соглашение:
один адрес обслуживает все типы файлов. Ветка default
возвращает содержимое как есть, поэтому Ctrl+B на файле
неизвестного типа ничего не испортит; в собственном преобразователе это
правило стоит сохранить.
Внутри может быть что угодно: минификация, обфускация, автоформатирование, прогон через сторонний сервис или локальную утилиту. Платформа не знает и не проверяет, что именно происходит, — ей важен только текст в ответе.
Проверку на локальный вызов не выбрасывайте. Преобразователь лежит в корне сайта, принимает произвольный текст и выполняется на вашем сервере — без неё запустить его сможет кто угодно из интернета. Тот же приём используют cron-модули, там для этого есть готовый метод
CronLocalOnly()(см. «Планировщик задач»).