OpenFL Project configuration for power users. Adam Breece

Title slide

В своем докладе Адам рассказал как в компании FlowPlay вместо обычно используемого практически всеми файла конфигурации проекта project.xml они использовали project.hxp.

Видео-версия доклада доступна на официальном сайте Haxe.

What is a project.xml

Project.hxp  - это еще один способ конфигурации OpenFL-проектов, но его описание задается не в xml-формате, а пишется полностью на Haxe, что позволяет вам использовать все средства языка. Это позволяет достичь больших результатов меньшими усилиями по сравнению с использованием xml-конфигов.

What is a project.hxp

На слайде показан файл project.hxp, в котором описана такая же конфигурация проекта, как и на предыдущем слайде.

Адам привел ряд простых примеров, легко реализуемых с помощью hxp-конфигов.
Это и программное добавление звуковых ассетов в проект с автоматическим присвоением id каждому звуку (в xml-конфиге это пришлось бы делать вручную).

Sound assets

Аналогично можно сделать и с иконками приложения. При этом вы получаете контроль над тем, как будут выглядеть иконки определенного размера (например, на разных устройствах от Apple).

Icon assets

В hxp-конфиге можно разрешить использовать какую-то определенную версию компилятора для проекта и запретить все остальные. В Vegas World это помогло избежать проблем со сборкой проектов, т.к. один и тот же код может не собираться на каких-то определенных версиях компилятора (но происходит это не сразу при запуске сборки проекта, а, например, в самом конце). Это позволяет сэкономить время, не тратя его на выяснение причин, почему код не собирается.

Enforcing compiler version

Importing project.xml into project.hxp

Кроме того, часть настроек проекта можно все так же задавать в xml-файле, а остальные - в hxp. В базовом классе HXProject есть все необходимые для этого средства:

  • загрузка и разбор настроек, заданных в xml, осуществляется с помощью класса ProjectXMLParser (из lime tools);
  • слияние настроек осуществляется с помощью метода merge().

Также в Vegas World каждая из мини-игр выделена в независимый модуль, являющийся синглтоном.

Reducing boilerplate Example module getter

На слайде приведен код одного из таких модулей - Lottery. Почти весь код модуля является шаблонным, меняются только фрагменты, выделенные оранжевым цветом. Такой код повторяется для всех 93 модулей Vegas World.
Использование шаблонов для генерации кода модулей позволяет избежать монотонного копи-пастинга (и возможных ошибок, связанных с ним).
Но главным преимуществом такого подхода является возможность разделения получаемого на выходе javascript-кода на отдельные модули. Для каждого модуля Vegas World (для каждой мини-игры) создается отдельный js-файл. Что позволяет загружать не всю игру целиком, а только нужные ее части.
Для это используется библиотека https://github.com/elsassph/haxe-modular 

Module getter template

На этом слайде приведен код шаблона, который используется для кодогенерации всех 93 модулей.

Game module list

Построение списка модулей в игре осуществляется в project.hxp на основании структуры папок проекта.

Copying the template

Затем по этому списку генерируется код модулей (с помощью стандартного шаблонизатора Haxe).

Enabling module

Использование такого подхода позволяет “фильтровать” модули - включать их в билд или отключать.
Для того, чтобы модуль попал в билд, необходимо задать для него define.
Если же не задать вообще ни одного define, то будет собран проект со всеми модулями (так сделано, чтобы разработчикам не нужно было задавать define для всех 93 модулей вручную).
Удобство механизма фильтрации модулей заключается в том, что каждый разработчик обычно одновременно работает над каким-то одним игровым модулем и ему требуется собирать только его. Фильтрация модулей позволяет это сделать.

Filtering enabled modules

Disabled module getter

Как видно из слайда, для отключенного модуля функция functionLoad() возвращает null.
И, так как вызов кода этого модуля осуществляется только в этом геттере, то возвращая null и не импортируя его код, мы отключаем модуль для всей игры. 

Reducing build time

Отключение модулей позволяет значительно сократить время сборки проекта на этапе разработки - в Vegas World проект с одним модулем в среднем собирается в 4 раза быстрее, чем со всеми включенными модулями. А это означает экономию времени разработчиков. 

Using other source files and haxelibs

Использование hxp-файлов позволяет разбивать их на отдельные специализированные части (например, один файл отвечает за загрузку звуков, второй - за иконки, третий - за построение списка модулей), иначе он превратился бы в огромную простыню.
Также в hxp-файле можно задавать флаги компиляции с помощью мета-тэга @:compiler().

Code reuse for module dependency checking

Адам поделился опытом того, как в FlowPlay контролируют отсутствие перекрестных ссылок между модулями проекта. Если не делать этого, то при сборке модуля, в котором есть ссылка на другой модуль, будут собраны оба модуля, а это означает увеличение размера билда - при этом теряется смысл разбиения проекта на отдельные модули (у пользователя будет загружаться сразу весь проект).
Для контроля за ссылками используется специальный инструмент (также на основе hxp), который собирает модули проекта по-одному (при этом остальные модули отключаются), и если при такой сборке модуля происходит сбой, то это означает, что в нем есть ссылка на другой модуль (отключенный в данный момент).
Этот инструмент используется для непрерывной интеграции.

Caveats of project.hxp

Однако при работе с hxp-проектами необходимо иметь в виду следующие моменты:

  • код в hxp-файлах исполняется каждый раз, когда выполняются команды build, update, test, run, display. Поэтому не следует помещать в них слишком уж “тяжелый” код.
  • Следует отключать логгер при использовании команды openfl display, т.к. в противном случае логирование может нарушить работу других инструментов, завязанных на display.

References

Если вас заинтересовала тема hxp-проектов в OpenFL, то рекомендуется ознакомиться с:

Также, если интересна тема модуляризации для js-проектов на Haxe, то рекомендуется посмотреть в сторону https://github.com/elsassph/haxe-modular (о котором был доклад на прошлом Haxe Summit - https://haxe.org/videos/conferences/haxe-summit-2017/haxe-modular-splitting-monolith-js-philippe-elsass.html