Au coeur d'Electron : Utilisation de Node en tant que Bibliothèque
Ceci est le deuxième article d’une série en cours expliquant le fonctionnement interne d'Electron. Consultez le premier post sur l'intégration de la boucle d'événement si vous ne l'avez pas déjà fait.
La plupart des gens utilisent Node pour les applications côté serveur, mais en raison de l’ensemble d’API riche de Node et de sa communauté florissante, il convient également parfaitement à une bibliothèque intégrée. Cet article explique comment Node est utilisé comme bibliothèque dans Electron.
Système de génération
Node et Electron utilisent GYP
comme systèmes de génération. Si vous souhaitez intégrer Node dans votre application, vous devez également l’utiliser comme système de génération.
Vous ne connaissez pas GYP
? Lisez ce guide avant de continuer dans cet article.
Node's flags
Le nœud yp
dans le répertoire de code source de Node décrit comment Node est construit, avec beaucoup de GYP
variables qui contrôlent quelles parties de Node sont activées et si pour ouvrir certaines configurations.
To change the build flags, you need to set the variables in the .gypi
file of your project. The configure
script in Node can generate some common configurations for you, for example running ./configure --shared
will generate a config.gypi
with variables instructing Node to be built as a shared library.
Electron does not use the configure
script since it has its own build scripts. Les configurations pour Node sont définies dans le fichier common.gypi
dans le répertoire du code source d'Electron.
Link Node with Electron
In Electron, Node is being linked as a shared library by setting the GYP
variable node_shared
to true
, so Node's build type will be changed from executable
to shared_library
, and the source code containing the Node's main
entry point will not be compiled.
Since Electron uses the V8 library shipped with Chromium, the V8 library included in Node's source code is not used. This is done by setting both node_use_v8_platform
and node_use_bundled_v8
to false
.
Shared library or static library
When linking with Node, there are two options: you can either build Node as a static library and include it in the final executable, or you can build it as a shared library and ship it alongside the final executable.
In Electron, Node was built as a static library for a long time. This made the build simple, enabled the best compiler optimizations, and allowed Electron to be distributed without an extra node.dll
file.
Cependant, cela a changé après que Chrome ait basculé pour utiliser BoringSSL. BoringSSL est un fork de OpenSSL qui supprime plusieurs API inutilisées et modifie de nombreuses interfaces existantes. Because Node still uses OpenSSL, the compiler would generate numerous linking errors due to conflicting symbols if they were linked together.
Electron n'a pas pu utiliser BoringSSL dans le nœud, ou utiliser OpenSSL dans Chromium, la seule option était donc de basculer vers la construction d'un noeud en tant que bibliothèque partagée, et cachent les symboles BoringSSL et OpenSSL dans les composantes de chacune.
This change brought Electron some positive side effects. Before this change, you could not rename the executable file of Electron on Windows if you used native modules because the name of the executable was hard coded in the import library. After Node was built as a shared library, this limitation was gone because all native modules were linked to node.dll
, whose name didn't need to be changed.
Supporting native modules
Modules natifs dans le travail de Noeude en définissant une fonction d'entrée pour le chargement de Noeud, puis la recherche des symboles de V8 et libuv à partir de Node. This is a bit troublesome for embedders because by default the symbols of V8 and libuv are hidden when building Node as a library and native modules will fail to load because they cannot find the symbols.
So in order to make native modules work, the V8 and libuv symbols were exposed in Electron. For V8 this is done by forcing all symbols in Chromium's configuration file to be exposed. Pour libuv, il est réalisé en définissant la définition BUILDING_UV_SHARED=1
définition.
Starting Node in your app
After all the work of building and linking with Node, the final step is to run Node in your app.
Node doesn't provide many public APIs for embedding itself into other apps. Habituellement, vous pouvez juste appeler node::Start
et node::Init
pour démarrer une nouvelle instance de Node. However, if you are building a complex app based on Node, you have to use APIs like node::CreateEnvironment
to precisely control every step.
In Electron, Node is started in two modes: the standalone mode that runs in the main process, which is similar to official Node binaries, and the embedded mode which inserts Node APIs into web pages. The details of this will be explained in a future post.