В Ahrefs мы используем BuckleScript и ReasonML в производстве более двух лет. У нас уже есть кодовая база из десятков тысяч строк кода с несколькими веб-приложениями, которые требуют большого объема данных и взаимодействуют с серверными службами, написанными на OCaml, с использованием таких инструментов, как atd.
Принимая во внимание наши инвестиции в эти технологии, мы внимательно следим за недавними изменениями в ReScript с его ребрендингом и переименованием, а также за разделением проекта ReasonML, описанным в сообщении блога проекта.
ReScript: стать отдельным языком
Мы очень довольны тем, как ReScript объединяет возможности и упрощает разработчикам, начинающим работу, поиск документации в одном месте, а также по-прежнему уделяет большое внимание производительности и удобочитаемости вывода JavaScript.
С другой стороны, мы пытаемся выяснить последствия этого изменения в среднесрочной и долгосрочной перспективе, особенно в отношении интеграции с экосистемой OCaml. И что еще более важно, что эта эволюция будет означать для таких производственных пользователей, как мы, которые полагаются на эту интеграцию.
Интеграция ReScript с OCaml исторически была беспроблемной, поскольку BuckleScript изначально создавался как новый бэкэнд для компилятора OCaml. Однако в последние месяцы появилось несколько намеков на то, что ReScript хочет развиваться, чтобы стать собственным языком:
- Теперь у него есть собственный парсер, несовместимый с нативными приложениями OCaml.
- В официальных правилах репозитория для написания технической документации прямо упоминается, что никакие ссылки на OCaml не должны появляться в документации.
- Обновления до последней версии компилятора OCaml, которые раньше были частью дорожной карты, недавно были лишены приоритета.
Таким образом, даже если официально ReScript не объявил о нарушении обратной совместимости с OCaml, сам факт того, что он придерживается старой версии компилятора OCaml, создает для нас некоторые проблемы с точки зрения инструментов. Неуверенность в будущем и темп изменений добавляют некоторый риск к высокоуровневым целям, которые мы ставим перед нашими командами и кодовой базой: мы хотели бы делиться большим кодом между интерфейсом и серверной частью, а не меньше.
Melange: форк ReScript, ориентированный на совместимость с OCaml.
Когда Антониу Монтейро анонсировал Melange, ответвление ReScript, но с упором на сохранение совместимости с OCaml, мы решили попробовать его и посмотреть, как он может сработать для нас.
В конечном итоге эксперимент удался. Нам удалось собрать все наши интерфейсные приложения с помощью Melange, сохранив при этом существующую настройку пакетирования, которая в настоящее время использует Webpack.
В ходе этого процесса нам пришлось изменить некоторые части кода. Теперь мы рассмотрим наиболее важные части процесса:
- Обновление до OCaml 4.12: наиболее важной частью было прекращение использования модуля
Pervasives
для использованияStdlib
. - Используйте ppxlib в наших ppx: нам пришлось обновить два ppx, которые мы используем в кодовой базе внешнего интерфейса, до последней версии компилятора, bs-Emotion-ppx и собственного ppx для интернационализации.
- Настроить
esy
: мы уже использовалиesy
для переноса инструментов редактора в область действия среды разработчика, поэтому нам просто нужно было убедиться, чтоmelange
также будет включен в конфигурацию json. - Обновление до Reason 3.7.0: тоже довольно простое изменение, так как весь процесс автоматизирован с использованием
refmt
. В качестве примечания, мы столкнулись с небольшой ошибкой с некоторыми аннотациями типов, которую мы смогли обойти. - «Поднимите» рабочее пространство дюн к корню нашего монорепозитория: это, наверное, самое навязчивое изменение. Поскольку у нас общий код между серверной частью и фронтендом, а Dune должен иметь доступ ко всем источникам в своей рабочей области, нам пришлось «поднять» рабочее пространство Dune из каталога
backend
в корень monorepo.
Добро
Этот эксперимент позволил нам испытать, что такой проект, как Melange, может предложить для нашего варианта использования. Вот некоторые из вещей, которые мы могли бы использовать в кодовой базе, созданной с помощью Melange:
- Последняя версия компилятора OCaml: в какой-то момент мы могли закрепить версию компилятора между командами бэкэнд и фронтенд, что упростило обновление, поскольку оно происходило бы атомарно.
- Общие инструменты редактора: официальное расширение vscode для OCaml отлично работает с Melange, а также с любой другой интеграцией редактора OCaml. Если бэкэнд- и фронтенд-команды используют схожую настройку редактора, нам не нужно выполнять много работы по обслуживанию.
- Потребление ppx из источника: Melange позволяет потреблять ppx из источника, что также устраняет проблемы с предварительно скомпилированными ppx (как эта проблема с недавними M1 Mac).
- Melange позволяет запускать все ppx из одного исполняемого файла, что дает хорошие преимущества в производительности.
- Используйте Dune для генераторов файлов atd: генераторы ReScript, к сожалению, больше не документированы, но мы широко используем их для генерации файлов atd. Возможность делиться правилами Dune в бэкэнде и во внешнем интерфейсе упростит настройку нашей сборки.
- Доступ к инструментам документации OCaml: Melange позволяет использовать существующие инструменты для создания документации, такие как odoc.
- Синтаксис Async: последняя версия Reason поддерживает синтаксис let op, что удобно для клиентского кода.
Плохо
Хотя в Меланже есть много интересных моментов, есть и другие части, которые можно улучшить.
- Производительность сборки: мы уже знали, что производительность будет намного хуже, чем у ReScript, поскольку Меланж использует Dune не так, как он был разработан. В наших тестах сборки с Melange примерно на 1 порядок медленнее, чем с ReScript.
- Первоклассная поддержка Dune: если бы между Dune и Melange была более глубокая интеграция, мы могли бы изучить такие функции, как общие библиотеки или общие правила между серверной частью и внешним интерфейсом. На сегодняшний день Dune ничего не знает о среде Melange, поэтому она может выполнять основные правила, но нет доступа к строфам высокого уровня, таким как
library
в Melange. - Двуглавая цель: наконец, мы видим более стратегический риск в предложении Меланжа. Сейчас у него две цели: сохранить совместимость как с ReScript, так и с OCaml. Но мы не знаем, как долго эти цели будут достижимы. Если в какой-то момент ReScript решит полностью отказаться от компилятора OCaml, то пользователи Melange больше не смогут получать какие-либо обновления экосистемы ReScript.
Хорошо, но вы переходите на Melange или ReScript?
Учитывая всю доступную информацию, ответ таков: мы еще не знаем. 😄 Мы хотим продолжить изучение всех доступных вариантов и получить как можно больше информации, прежде чем совершать дальнейшие действия. Итак, на данный момент мы обновляем кодовую базу до последних версий ReScript, но задерживаем функции, которые работают только в одном направлении. Например, мы еще не перевели нашу кодовую базу на синтаксис ReScript, так как нет возможности вернуться к синтаксису Reason.
А пока мы продолжим изучать, насколько можно смягчить ограничения Melange. Продолжение следует! 🚀
Спасибо Игорю и Фейхонгу за просмотр и улучшение предыдущих версий этого сообщения.