Hacemos una aplicación de escritorio nativa multiplataforma en Angular

angular-nodegui


Como probablemente ya sepa, Angular ya existe en muchas plataformas:



Bueno, por supuesto, no había suficiente escritorio aquí (no hablemos de Electron todavía).


Para crear aplicaciones de escritorio, hay muchas soluciones que usan plantillas, por ejemplo, soluciones como JavaFx, Qt, WPF. Todos ellos, excepto el último, son multiplataforma.


Pero, ¿qué pasaría si quisiéramos usar el marco familiar y hacer una aplicación nativa en él? En realidad, eso fue lo que hice.


Para empezar, miré lo que está disponible actualmente y lo que ya se pudo haber hecho en Angular.


De hecho, de esta manera quiero demostrar que puedes hacer cualquier cosa en Angular, y durante varios años he estado haciendo todo tipo de cosas por él .

Buscar


nodo libui


Es una biblioteca GUI liviana y portátil que aprovecha las características nativas de la GUI para cada plataforma que admite. Viene como una alternativa al electrón.


Un ejemplo de aplicación simple:


const win = new libui.UiWindow('Test window', 800, 600, false); 

Bajo el capó, él tiene simples carpetas de libui. (libui: una biblioteca GUI portátil para C). Todo esto está pasando por node-gyp, una utilidad diseñada para compilar extensiones nativas para Node.js. libui-node incluye más de 30 componentes listos, bueno, y si de repente decides crear algo personalizado, necesitarás sumergirte en el código en C. Y además, los componentes en sí mismos se escribieron hace 2 años, y desde entonces actualizado Quizás todo es tan bueno que no hay necesidad de hacer cambios, y estos 30 componentes son suficientes para el desarrollo, bueno, o nadie necesita el proyecto en absoluto.


Bueno, en realidad, la aplicación final puede verse así:


nodo libui nodo libui


Proton-native y Vuido


Y aquí es un poco más interesante, proton-native y vuido es el mismo nodo libui, solo bajo React y Vue. Los contenedores correspondientes están escritos bajo los componentes de libui-node. A pesar de la cantidad de estrellas en github (9k y 6k), los proyectos están abandonados y casi nadie los usa. De todo lo que pude encontrar, estas fueron aplicaciones muy simples. Otro problema que descubrí son los problemas con la personalización de la propia interfaz de usuario, es imposible hacerlo dentro de libui, y el autor del proyecto está considerando reescribir todo en Qt.


Libui en sí es bastante popular para escribir todo tipo de enlaces, los entusiastas lo arrastraron incluso en php

La aplicación final puede verse así:


Nativo de protones Nativo de protones


Una interfaz bastante aburrida sin personalización, por lo que esta opción desapareció de inmediato.


O tal vez tomar Qt?


Qt, js, css


Por supuesto que escuchó sobre Qt y el hecho de que se puede encontrar en todas partes, pero no muchos han escuchado que ahora está integrado con Javascript fuera de la caja. QML permite la construcción declarativa de interfaces de usuario utilizando ligantes de propiedades y, por lo tanto, expandiendo la capacidad de los elementos QML existentes. Por supuesto, este es Javascript más riguroso que en la web. Puede escribir algo similar a ES5 utilizando objetos QML, pero no tendrá una API DOM.


Solo una nota rápida, ¿cómo escribirías en Qt bajo C ++:


 #include <QApplication> #include <QPushButton> int main(int argc, char *argv[]) { QApplication app(argc, argv); *// Important * QPushButton hello("Hello world!"); hello.resize(100, 30); hello.show(); return app.exec(); *// Important *} 

Cómo se vería su código en Qml:


 Item { function factorial(a) { a = parseInt(a); if (a <= 0) return 1; else return a * factorial(a - 1); } MouseArea { anchors.fill: parent onClicked: console.log(factorial(10)) } } 

Estos componentes se pueden crear dinámicamente.


QML también tiene un sistema de tipo grande, que sin duda será útil al definir todo esto en Typecript.


También puede personalizar fácilmente los componentes:


 Reactangle { id: redRectId width: 50 color: red } 

Casi CSS, ¿no?


Todo lo que queda por agregar es lo que Qt puede hacer en la mayoría de las plataformas.


Y tendríamos Node.js


Al buscar “nodejs + qt”, obtendremos inmediatamente node-qt , pero inmediatamente llama la atención que el producto ha estado muerto hace mucho tiempo, y la última vez mostró signos de vida hace 8 años.


Sin embargo, en la búsqueda puede encontrar un proyecto muy nuevo: NodeGui.


NodeGui


Al igual que muchas bibliotecas para Gui, Qt usa su bucle de evento / mensaje para procesar eventos desde widgets. Por lo tanto, cuando llamamos condicionalmente a app.exec (), Qt inicia el bucle de mensajes y lo bloquea allí. Todo esto es bueno cuando solo hay un bucle de mensaje en toda la aplicación. Pero dado que necesitamos usar Qt con NodeJs, y este último también tiene su propio bucle de eventos, es imposible integrarlos tan fácilmente. Pero tales decisiones ya se han tomado, por ejemplo, el mismo paquete con Electron o yode. Estas soluciones tienen su propia peculiaridad, generan al menos 2 procesos: para el hilo principal y para el renderizador. A pesar de esto, este enfoque tiene una ganancia significativa, no es necesario modificar NodeJs o Chromium.


En el caso de NodeGui, la situación es ligeramente diferente, hay un proceso para todo y, por lo tanto, no hay necesidad de buscar eventos entre procesos. Nodejs se bifurcó para esto, y se realizaron mejoras menores en las carpetas necesarias en Qt. Y ahora necesita comenzar el proceso no de la forma habitualnode main.js, sino qode main.js. Afortunadamente, qode se publica como un módulo npm en el paquete @ nodegui / qode. Para comenzar un mundo hola simple, necesita instalar algunos paquetes más, para obtener más detalles sobre cada sistema operativo, consulte el sitio web oficial: https://docs.nodegui.org/docs/guides/getting-started


Por defecto, en nodegui, todo es un widget, y se pueden atornillar a varias plantillas. Actualmente hay 2 tipos de plantillas en nodegui: FlexLayout y QGridLayout.


Estilos en Nodegui


Por el momento, puede establecer estilos para widgets tanto en línea como a través de styleSheet.


 widget.setInlineStyle(`color: green`) view.setStyleSheet(` `#helloLabel { color: red; padding: 10px; } #worldLabel { color: green; padding: 10px; } #rootView { background-color: black; } `); 

Qt por defecto admite todos los selectores CSS2 ( https://doc.qt.io/qt-5/stylesheet-syntax.html#selector-types )


Tampoco lo hace sin propiedades personalizadas para los componentes de estilo. Afortunadamente, tales propiedades ya se describen en los muelles de Qt y se mastican en stackoverflow.


 *QPushButton* { qproperty-iconsize: 20px 20px; } 

Angular


El autor del proyecto ya ha implementado el soporte para reaccionar, pero por supuesto, todos olvidaron la existencia de Angular.

Como ya se escribió al principio, Angular puede hacer la mayoría de las plataformas, pero hasta ahora no ha habido una plataforma para el escritorio. Debido a la API Angular bien diseñada y estructurada, la implementación de nodegui para Angular se reduce a escribir una plataforma personalizada BrowserDynamics con Renderer y reemplazarlos en la aplicación.


Pero, ¿cómo funciona todo de adentro hacia afuera?


Tenemos un main.ts condicional, y comenzaremos con él.


El proceso de arranque consta de dos partes: crear una plataforma y lanzar un módulo de inicio.


 platformBrowserDynamic().bootstrapModule(AppModule); 

A través de createPlatformFactory podemos crear absolutamente cualquier plataforma que necesite. Para nosotros, esto significa que no queremos trabajar con el DOM habitual y, además, repasaremos la descripción del esquema de interacción de elementos al trabajar con el render. Puede encontrar más información sobre la creación de la plataforma en la fuente.


En el módulo de inicio, describimos qué componente representar primero. Al crear una instancia de un componente, Angular llama renderComponent y, asociándolo con el render deseado que recibe, con esa instancia del componente. Todo lo que Angular hará con respecto a la representación de componentes (crear elementos, establecer atributos, suscribirse a eventos, etc.) pasará por este renderizador. Por lo tanto, debemos reemplazar la RendererFactory.


En primer lugar, en Renderer nos interesará el método createElement. En este método, obtenemos el nombre de la etiqueta y, a partir de ella, necesitamos crear el componente deseado. Afortunadamente, nodegui tiene un conjunto básico de componentes, que porté cuidadosamente y describí cómo se representarán en el marco de Angular, arrojando todo al directorio general de componentes. Otras acciones con componentes estándar también pasarán por este renderizador. Más detalles


[https://blog.nrwl.io/†(https://blog.nrwl.io/) https://blog.nrwl.io/


Para escuchar eventos en el renderizador, se lanza el nombre del evento y para estos componentes colgamos el eventListener habitual.


 listen(target: any, eventName: string, callback: (event: any) => boolean | void): () => void { const callbackFunc = (e: NativeEvent) => callback.call(target, e); target.addEventListener(eventName, callbackFunc); return () => target.removeEventListener(eventName, callbackFunc); } 

Los eventos de componentes son exactamente los mismos que Qt, por ejemplo, en lugar del usual (click)=”clickFunc($event)” debe escribir (clicked) = ”clickFunc($event)” .


Actualmente hay 16 componentes estándar disponibles. Pero si necesita escribir su componente personalizado, siempre existe la oportunidad de hacerlo a través de QWidget.


También se hizo un enrutador para hacer que nuestra aplicación sea lo más compatible posible con Angular.


 const appRoutes: Routes = [ { path: 'home', component: HomeComponent }, { path: 'about', component: AboutComponent } ]; // AppModule imports ... NodeguiRouterModule.forRoot(appRoutes), 

Aplicación angular nodegui
Aplicación angular nodegui


aplicación meteorológica
aplicación meteorológica


Recopilamos en prod


Para construir una aplicación lista para usar, nodegui tiene su propio empaquetador - @nodegui/packer.


La utilidad es muy simple, hasta ahora consta de 2 equipos.


npx nodegui-packer - init myapp


Este comando creará una carpeta de empaque que contiene la plantilla. Puede cambiar el contenido para agregar un icono, cambiar el nombre, la descripción y otra información de la aplicación, así como agregar las dependencias necesarias.


npx nodegui-packer - paquete

Este comando inicia la herramienta necesaria para empaquetar (por ejemplo, macdeployqt para mac) y empaqueta las dependencias.


En conclusión


En conclusión, quiero comparar los resultados con otras soluciones web en el escritorio (resultados del lanzamiento en Mac OS).


tamaño de descarga tamaño de descarga


uso de memoria uso de memoria



Enlace al proyecto:
irustm / angular-nodegui
* Cree aplicaciones de escritorio performantes, nativas y multiplataforma con Angular. Angular NodeGUI es impulsado por Angular


Información sobre el proyecto:
https://t.me/ngFanatic


Información sobre mis proyectos de código abierto
https://twitter.com/irustm

Source: https://habr.com/ru/post/480396/


All Articles