
Введение
Wails — это проект, который упрощает разработку кроссплатформенных настольных приложений на Go. Для интерфейса он использует нативные компоненты webview, а не встроенные браузеры. Благодаря этому разработчикам на Go доступны возможности самой популярной в мире системы создания пользовательских интерфейсов, при этом приложения остаются легковесными.
Версия 2 была выпущена 22 сентября 2022 года и принесла множество улучшений, включая:
- Разработку в реальном времени с использованием популярного проекта Vite
- Широкие возможности управления окнами и создания меню
- Компонент WebView2 от Microsoft
- Генерацию моделей Typescript, соответствующих вашим структурам Go
- Создание установщика NSIS
- Обфусцированные сборки
Сейчас Wails v2 предоставляет мощный набор инструментов для создания функциональных кроссплатформенных настольных приложений.
В этой статье мы рассмотрим текущее состояние проекта и то, что можно улучшить в дальнейшем.
Где мы сейчас?
Невероятно видеть, как растёт популярность Wails после выпуска v2. Меня неизменно восхищают творческий подход сообщества и замечательные проекты, создаваемые с помощью Wails. Чем популярнее становится проект, тем больше внимания он привлекает, а вместе с ним растёт число запросов на новые функции и сообщений об ошибках.
Со временем мне удалось определить несколько наиболее насущных проблем проекта. Я также выявил некоторые факторы, которые сдерживают его развитие.
Текущие проблемы
Я выделил следующие области, которые, на мой взгляд, сдерживают развитие проекта:
- API
- Генерация привязок
- Система сборки
API
В настоящее время API для создания приложения Wails состоит из 2 частей:
- API приложения
- API среды выполнения
Как известно, API приложения содержит всего 1 функцию: Run(), которая принимает множество параметров, определяющих работу приложения. Такой API очень прост в использовании, но при этом существенно ограничивает возможности. Это «декларативный» подход, скрывающий значительную часть внутренней сложности. Например, он не предоставляет дескриптор главного окна, поэтому напрямую взаимодействовать с ним невозможно. Для этого приходится использовать API среды выполнения. Когда требуется реализовать более сложные сценарии, например создать несколько окон, это становится проблемой.
API среды выполнения предоставляет разработчику множество вспомогательных функций, в том числе:
- Управление окнами
- Диалоговые окна
- Меню
- События
- Журналы
В API среды выполнения меня не устраивает несколько моментов. Во-первых, он требует повсюду передавать «контекст». Это неудобно и сбивает с толку начинающих разработчиков, которые передают контекст, а затем получают ошибку времени выполнения.
Главная проблема API среды выполнения заключается в том, что он был рассчитан на приложения только с одним окном. Со временем потребность в нескольких окнах выросла, а API плохо подходит для такого сценария.
Мысли об API v3
Было бы здорово иметь возможность делать что-то подобное, не правда ли?
func main() {
app := wails.NewApplication(options.App{})
myWindow := app.NewWindow(options.Window{})
myWindow.SetTitle("My Window")
myWindow.On(events.Window.Close, func() {
app.Quit()
})
app.Run()
}Такой программный подход гораздо понятнее и позволяет разработчику напрямую взаимодействовать с элементами приложения. Все существующие методы среды выполнения для работы с окнами стали бы обычными методами объекта окна. Остальные методы среды выполнения можно было бы перенести в объект приложения следующим образом:
app := wails.NewApplication(options.App{})
app.NewInfoDialog(options.InfoDialog{})
app.Log.Info("Hello World")Это гораздо более мощный API, который позволит создавать более сложные приложения. Он также позволит создавать несколько окон — самую востребованную функцию на GitHub:
func main() {
app := wails.NewApplication(options.App{})
myWindow := app.NewWindow(options.Window{})
myWindow.SetTitle("My Window")
myWindow.On(events.Window.Close, func() {
app.Quit()
})
myWindow2 := app.NewWindow(options.Window{})
myWindow2.SetTitle("My Window 2")
myWindow2.On(events.Window.Close, func() {
app.Quit()
})
app.Run()
}Генерация привязок
Одна из ключевых возможностей Wails — генерация привязок для методов Go, позволяющая вызывать их из Javascript. Текущий способ реализации больше похож на обходной приём. Приложение собирается со специальным флагом, после чего запускается полученный исполняемый файл, который с помощью рефлексии определяет, для каких элементов созданы привязки. Возникает своего рода проблема курицы и яйца: приложение нельзя собрать без привязок, а привязки нельзя сгенерировать без сборки приложения. Эту проблему можно обойти разными способами, но лучшим решением было бы полностью отказаться от данного подхода.
Предпринималось несколько попыток написать статический анализатор для проектов Wails, но значительного прогресса добиться не удалось. В последнее время эта задача стала немного проще, поскольку появилось больше материалов по теме.
Подход на основе AST намного быстрее рефлексии, однако он значительно сложнее. На первом этапе, возможно, потребуется ввести определённые ограничения на описание привязок в коде. Цель — сначала поддержать самые распространённые сценарии использования, а затем расширить возможности.
Система сборки
Как и декларативный подход к API, система сборки была создана, чтобы скрыть сложности сборки настольного приложения. При запуске wails build она автоматически выполняет множество действий, скрывая от пользователя детали:
-
Собирает исполняемый файл бэкенда для привязок и генерирует привязки
-
Устанавливает зависимости фронтенда
-
Собирает ресурсы фронтенда
-
Проверяет наличие значка приложения и встраивает его, если он найден
-
Собирает окончательный исполняемый файл
-
Если сборка предназначена для
darwin/universal, собирает 2 исполняемых файла: один дляdarwin/amd64и один дляdarwin/arm64, после чего с помощьюlipoсоздаёт универсальный исполняемый файл -
Если требуется сжатие, сжимает исполняемый файл с помощью UPX
-
Определяет, нужно ли упаковать этот исполняемый файл, и если да:
- Обеспечивает встраивание значка и манифеста приложения в исполняемый файл (Windows)
- Создаёт пакет приложения, генерирует комплект значков и копирует его, исполняемый файл и Info.plist в пакет приложения (Mac)
-
Если требуется установщик NSIS, собирает его
Весь этот процесс, хотя и обладает очень широкими возможностями, также совершенно непрозрачен. Его очень сложно настраивать и отлаживать.
Чтобы решить эту проблему в v3, я хотел бы перейти на систему сборки, существующую отдельно от Wails. Некоторое время поработав с Task, я стал её большим поклонником. Это отличный инструмент для настройки систем сборки, который должен быть достаточно знаком всем, кто работал с Makefile.
Система сборки настраивалась бы с помощью файла Taskfile.yml, который по умолчанию создавался бы при использовании любого из поддерживаемых шаблонов. Он содержал бы все этапы, необходимые для выполнения всех текущих задач, таких как сборка или упаковка приложения, и позволял бы легко их настраивать.
Устанавливать этот инструмент отдельно не потребуется, поскольку он станет частью Wails CLI. Это означает, что вы по-прежнему сможете использовать wails build, и эта команда будет выполнять всё то же, что и сейчас. Однако при необходимости настроить процесс сборки вы сможете отредактировать файл Taskfile.yml. Кроме того, вы сможете легко разобраться в этапах сборки и при желании использовать собственную систему сборки.
Недостающее звено в системе сборки — атомарные операции процесса сборки, такие как создание значков, сжатие и упаковка. Необходимость устанавливать множество внешних инструментов ухудшила бы удобство разработки. Чтобы этого избежать, Wails CLI будет предоставлять все эти возможности как часть интерфейса командной строки. Это означает, что сборка продолжит работать как ожидается без дополнительных внешних инструментов, но при этом любой её этап можно будет заменить любым подходящим инструментом.
Система сборки станет гораздо прозрачнее, что упростит её настройку и позволит устранить многие связанные с ней проблемы, о которых сообщали пользователи.
Результат
Эти положительные изменения принесут проекту огромную пользу:
- Новый API будет гораздо понятнее и позволит создавать более сложные приложения.
- Применение статического анализа для генерации привязок значительно ускорит процесс и устранит многие сложности текущего подхода.
- Использование проверенной внешней системы сборки сделает процесс сборки полностью прозрачным и предоставит широкие возможности настройки.
Преимущества для сопровождающих проекта:
- Новый API будет гораздо проще сопровождать и адаптировать к новым возможностям и платформам.
- Новую систему сборки будет гораздо проще сопровождать и расширять. Надеюсь, благодаря этому появится новая экосистема создаваемых сообществом конвейеров сборки.
- Более чёткое разделение ответственности внутри проекта упростит добавление новых возможностей и платформ.
План
Значительная часть экспериментов уже проведена, и результаты выглядят многообещающе. Точных сроков выполнения этой работы пока нет, но я надеюсь, что к концу первого квартала 2023 появится альфа-версия для Mac, которую сообщество сможет тестировать, с которой сможет экспериментировать и по которой сможет оставлять отзывы.
Итоги
- API v2 имеет декларативный характер, многое скрывает от разработчика и не подходит для таких возможностей, как работа с несколькими окнами. Будет создан новый API — более простой, понятный и мощный.
- Система сборки непрозрачна и плохо поддаётся настройке, поэтому мы перейдём на внешнюю систему сборки, которая сделает весь процесс открытым.
- Генерация привязок выполняется медленно и устроена сложно, поэтому мы перейдём на статический анализ, который устранит многие сложности текущего метода.
Во внутреннюю реализацию v2 вложено много труда, и она надёжна. Теперь пришло время заняться надстроенным над ней слоем и сделать работу разработчика гораздо удобнее.
Надеюсь, вы рады этому не меньше меня. С нетерпением жду ваших мнений и отзывов.
С уважением,
‐ Lea
P. S. Если вы или ваша компания считаете Wails полезным, пожалуйста, рассмотрите возможность стать спонсором проекта. Спасибо!
P. P. S. Да, это настоящий снимок экрана многооконного приложения, созданного с помощью Wails. Это не макет. Оно реально. Оно потрясающее. И скоро появится.