Как вы уже наверно знаете, Angular уже есть во многих платформах: Ну и, конечно, здесь не хватало десктопа (не будем пока про Electron). Для создания десктоп приложений существует много решений с использованием шаблонов, например, такие решения как JavaFx, Qt, WPF. Все они, кроме последней, являются кросплатформенными. А что если бы мы хотели использовать знакомый нам фреймворк и сделали бы на нем нативное приложение? Собственно, этим я и занялся. Для начала посмотрел что есть на текущий момент, и что уже, возможно, было сделано под Angular. Это легкая, портативная библиотека графического интерфейса, которая использует нативные возможности GUI, для каждой платформы, которую она поддерживает. Идет как альтернатива Еlectron. Пример простого приложения: Под капотом у него простые биндинги на libui. (libui: a portable GUI library for C). Собирается все это через node-gyp, утилиту, предназначенную для компилирования нативных расширений для Node.js. libui-node включает в себя более 30 готовых компонентов, ну, и если вам вдруг вздумается что то кастомное сотворить, то необходимо будет погрузиться в код на C. И к тому же, сами компоненты были написаны 2 года назад, и с тех пор не обновлялись. Возможно настолько все хорошо, что не нужно вносить изменения, и этих 30 компонентов вполне хватает для разработки, ну или проект никому и не нужен совсем. Ну и, собственно, готовое приложение может выглядит вот так: libui-node А вот тут немного интересней, proton-native и vuido это тот же самый libui-node, только под React и Vue. Под компоненты libui-node написаны соответствующие обертки. Несмотря на количество звезд на github(9к и 6к), проекты заброшены, и почти никто не использует. Из всего что смог найти, это были очень простые приложения. Еще одну проблему, которую я обнаружил, это проблемы с кастомизацией самого UI, это невозможно сделать в рамках libui, и автор проекта подумывает переписать все на Qt. Готовое приложение может выглядеть следующим образом: Proton-native Довольно скучный интерфейс без кастомизации, поэтому этот вариант отпал сразу. Конечно же вы слышали про Qt, и то, что его можно обнаружить везде, но не многие слышали что он из коробки сейчас интегрирован с Javascript. QML позволяет декларативное построение пользовательских интерфейсов, используя биндинги по свойствам и, тем самым, позволяя расширять возможность существующих QML элементов. Конечно же это более строгий Javascript чем в вебе. Можно писать нечто на подобии ES5 c использованием QML объектов, но у вас не будет DOM API. Просто на заметку, как бы вы писали на Qt под C++: Как может выглядеть ваш код в Qml: Эти компоненты возможно создавать динамически. А ещё QML имеет большую систему типов, что несомненно будет полезно при определении всего этого в Typescript. Так же можно легко кастомизировать компоненты: Почти CSS, не правда ли? Ко всему этому осталось добавить только что Qt умеет в большинство платформ. При поиске “nodejs + qt” нам сразу же выдаст node-qt, но сразу же бросается в глаза что продукт уже давно мертвый, и последний раз подавал признаки жизни 8 лет назад. Но тем не менее, в поиске можно обнаружить совсем свежий проект — NodeGui. Как и многие библиотеки для Gui, Qt использует свой event/message loop для обработки событий из виджетов. Следовательно, когда мы вызываем условно app.exec() Qt запускает цикл сообщений и блокирует его там же. Все это хорошо, когда есть только один цикл сообщений во всем приложении. Но поскольку нам необходимо использовать Qt с NodeJs и, последний, к тому же имеет свой event loop, невозможно их так легко интегрировать. Но такие решения уже были сделаны, например та же связка с Electron или yode. У этих решений существует своя особенность, они поднимают как минимум 2 процесса — для главного потока, и для рендерера. Несмотря на это, у этого подхода есть существенный выигрыш, не нужно модифицировать NodeJs или Chromium. В случае с NodeGui ситуация немного иная, есть один процесс для всего, и тем самым, нет необходимости шарить события между процессами. Для этого был форкнут Nodejs— и были сделаны небольшие доработки для необходимых биндингов в Qt. И теперь необходимо запускать процесс не так как обычноnode main.js, а qode main.js. К счастью, qode опубликован как npm модуль в пакет @nodegui/qode. Для того чтобы запустить простой hello world вам необходимо установить еще немного пакетов, подробнее для каждой ОС вы можете посмотреть на официальном сайте: https://docs.nodegui.org/docs/guides/getting-started По умолчанию в nodegui все является виджетами, и их можно прикручивать к различным шаблонам. В nodegui на данный момент имеется 2 типа шаблона: FlexLayout и QGridLayout.  Стили в Nodegui На данный момент можно задавать стили для виджетов как inline, так и через styleSheet. Qt по умолчанию поддерживает все селекторы в рамках CSS2 (https://doc.qt.io/qt-5/stylesheet-syntax.html#selector-types) Так же не обходится без кастомных свойств для стилизации компонентов. К счастью, такие свойства уже описаны в доках Qt и разжеваны на stackoverflow. Как уже писал в начале, Angular умеет в большинство из платформ, но до сих пор не было платформы под десктоп. Из-за хорошо продуманного и структурированного API Angular, реализация nodegui под Angular сводится к написанию кастомного platformBrowserDynamic с Renderer и их подменой в приложении. Но как это все работает изнутри? У нас есть условный main.ts, c него и начнем. Процесс начальной загрузки состоит из двух частей: создания платформы и прокидывания в него стартового модуля. Через createPlatformFactory мы можем создать абсолютно любую нужную платформу. Для нас это означает, что мы не хотим работать с обычным DOM, и дополнительно прокинем описание схемы взаимодействия элементов при работе с рендером. Подробнее про создание платформы можно ознакомиться в исходниках. В стартовом модуле мы описываем какой компонент рендерить первым. При создании экземпляра компонента Angular вызывает renderComponent и, связывая его с нужным рендером, которое он получает, с этим экземпляром компонента. Все, что Angular будет делать в отношении рендеринга компонента (создание элементов, настройка атрибутов, подписка на события и т. д.), будет проходить через этот рендерер. Поэтому нам необходимо подменить RendererFactory. В первую очередь в Renderer нас будет интересовать метод createElement. В этом методе мы получаем название тега, и по нему нам необходимо создать нужный компонент. Благо, в nodegui есть базовый набор компонентов, который я бережно перенес и описал как они будут рендерится в рамках Angular, закинув все в общий справочник компонентов. Остальные действия со стандартыми компонентами так же будут проходить через этот рендерер. Подробнее. https://blog.nrwl.io/ Чтобы слушать события в рендерер прокидывается название события, и для этих компонентов вешаем обычные eventListener. События компонентов в точности такие же как и Qt, например, вместо привычного (click)=”clickFunc($event)” необходимо писать (clicked) = ”clickFunc($event)”. На данный момент доступно 16 стандартных компонентов. Но если необходимо написать свой кастомный компонент, то всегда имеется возможность сделать это через QWidget. Также был сделан свой роутер, чтобы наше приложение было максимально совместимо с Angular. 
Angular nodegui app 
weather app Для того чтобы собирать готовое приложение в nodegui существует свой упаковщик — @nodegui/packer. Утилита очень простая, состоит пока из 2х команд. npx nodegui-packer — init MyApp Эта команда создаст папку для упаковывания, содержащий шаблон. Вы можете изменить содержимое, чтобы добавить иконку, изменить название, описание и другую информацию приложения, а также, чтобы добавить нужные зависимости. npx nodegui-packer — pack 
 Эта команда запускает нужный инструмент для упаковки(например,macdeployqt для mac) и упаковывает зависимости. В заключениe, хочется сравнить результаты с другими веб решениями на десктопе (результаты запуска под Mac OS). download size memory use Ссылка на проект:
irustm/angular-nodegui
*Build performant, native and cross-platform desktop applications with Angular. Angular NodeGUI is powered by Angular Информация про проект:
https://t.me/ngFanatic Информация про мои open source проекты
https://twitter.com/irustm