Деление проекта на правила и модули позволяет сформировать в модулях набор функций на все случаи жизни, охватив большинство типовых ситуаций. Если покрыть этот набор юнит-тестами, то можно в любой момент времени гарантировать, что ни один алгоритм не отклонился от своего изначального замысла:
Обычно пожелания клиента задействуют лишь часть возможностей, поэтому при установке правил на контроллер многие модули остаются не у дел - кто-то решил обойтись без многоканальных счётчиков электроэнергии, а кому-то достаточно автоматизаций, ориентированных на управление освещением.
Что, если бы существовал инструмент, способный готовить для отправки на контроллер Wirenboard только задействованный код? Для выключения модулей понадобится сформировать граф связей и отследить, какие части кода никогда не будут выполнены в текущем проекте.
В действительности, такие инструменты существуют и называются сборщиками модулей или бандлерами (Module Bundler). При этом, процесс удаления лишнего кода носит название Tree-Shaking.
Разумеется, функционал бандлеров не ограничивается одной лишь «тряской деревьев». Остальное задействуем по мере выхода новых статей. Подпишитесь, чтобы не пропустить - будет интересно!
После изучения различных систем сборки, следует отметить - многие из них либо слишком ориентированы на web-разработку, либо очень сложны в настройке.
Первоначально должна была выйти статья о Webpack, однако на его опциях и плагинах можно спокойно защитить пару пространных диссертаций. Наши исследования носят сугубо прикладной характер, поэтому на первое место вышел сборщик под названием Rollup. Работу с ним и рассмотрим далее.
Устанавливаем и настраиваем Rollup
В открытом проекте, созданном по материалам прошлых статей, запустим терминал VS Code и выполним команду
yarn add --dev rollup @rollup/plugin-multi-entry rollup-plugin-delete
Это добавит сборщик Rollup и его плагин, позволяющий разделить файлы в папке wb-rules на независимые точки входа. Другой плагин под названием plugin-delete, применяется для очистки целевой директории от прежних файлов.
Следом выполним команду
yarn add --dev tslib @rollup/plugin-typescript
Это даст возможность работы с кодом на языке TypeScript.
ℹ️ На заметку: отдельного внимания заслуживает плагин минификации @rollup/plugin-terser, позволяющий проводить глубокую оптимизацию результирующего кода. Однако, до него ещё дойдёт черёд - сейчас конвейер сборки настроен на совместимость с правилами wb-rules 2.0, которые крутятся на ECMAScript 5, а Babel перекрывает результат работы плагина.
Конфигурация сборщика модулей
В корень проекта добавим файл с именем rollup.config.mjs - он определит, как именно Rollup будет работать с кодом правил.
Первыми строками импортируем плагины:
import multi from '@rollup/plugin-multi-entry'
import typescript from '@rollup/plugin-typescript'
import del from 'rollup-plugin-delete'
Следом экспортируем объект конфигурации:
export default {
input: ['src/wb-rules/*.ts'],
plugins: [
multi({ preserveModules: true }),
typescript(),
del({ targets: ['build/*', 'dist/*'] })
],
output: {
format: 'es',
dir: 'build',
preserveModules: true
}
}
Здесь директивой input задаём шаблон для поиска файлов правил wb-rules в каталоге src/wb-rules. Папку с модулями не указываем намеренно - тогда файлы из неё считаются зависимостями, подлежащими анализу на предмет лишнего кода.
Следом перечисляем плагины, выполняющие обработку кода - здесь используется разделение точек входа и плагин для работы с TypeScript.
В настройках выхода результирующего кода обозначаем формат сборки "ES" и целевую директорию build - в неё будем помещать сырой код, подлежащий доводке для совместимости с контроллером Wirenboard (понадобится применить к нему tsc-alias для удаления лишней части путей при разрешении модулей и Babel для конвертации в ECMAScript 5).
Оптимизация конфигурации Babel
Поскольку @rollup/plugin-multi-entry создаёт в папке build лишнюю директорию _virtual, для того чтобы Babel не тащил её в код для отправки на контроллер, откроем в корне проекта его конфигурацию babel.config.json и добавим исключение из обработки:
{
"ignore": ["*/_virtual"],
"presets": ["@babel/preset-env"]
}
Настройка команды сборки проекта
Перейдём в файл package.json и найдём в секции scripts конвейерную команду build. Заменим её содержимое на следующее:
eslint && yarn test && rollup -c && tsc-alias && babel build -d dist
Как видно, поменялся только вызов tsc - вместо него теперь работает Rollup.
Проверяем функционирование
Перед запуском команды сборки видно, что в итоговом коде правил wb-rules сохранены все конструкции модуля, включая незадействованные:
Выполняем команду проекта build и наблюдаем, как из открытого файла dist/wb-rules-modules/example-module.js исчезли лишние функции:
Изменим код правила src/wb-rules/example.ts таким образом, чтобы он не обращался к модулю src/wb-rules-modules/example-module.ts - поскольку больше нет правил, ссылающихся на модуль, это приведёт к полному его удалению из целевой папки dist:
Можно заметить, что структура каталога dist поменялась - из него исчезла папка wb-rules. Это можно назвать артефактом работы плагина multi-entry и связано оно с тем, что нет ни одного модуля, позволяющего сформировать иерархию каталогов.
Напишите в комментариях, как вы обошли эту особенность?
Шаблон проекта на GitHub
Настроенный проект для разработки правил wb-rules доступен на GitHub. Код основной ветки дополнен материалами данной статьи и успешно прошёл проверку на работоспособность.
Послесловие
Использование системы сборки открывает широкие возможности для ещё большей автоматизации процесса разработки.
Основываясь на технологии Tree-Shaking, можно задействовать конфигурацию окружения и добавлять или удалять целые ветки кода, в зависимости от какого-нибудь параметра вроде
USE_MASTERSWITCH=yes
Возможно также создать различные файлы конфигураций для режимов development и production. Кроме того, настройки больше не будут разбросаны по множеству файлов правил.
Работа с конфигурациями окружения рассматривается в следующей статье из серии правил wb-rules: