Développons une application multiplateforme, basée sur JavaScript, Node.js et pkg
Parce que pourquoi pas
Le 26 juin 2018 à 08h45
8 min
Logiciel
Logiciel
Après vous avoir appris à développer vos premières applications de manière assez classique, nous nous portons vers une solution plus inhabituelle. Nous utiliserons pour cela JavaScript et Node.js pour un résultat multiplateforme.
Lorsqu’on cherche à présenter Node.js à des utilisateurs n'ayant jamais mis le nez dans cette plateforme, il est de bon ton de commencer par un tutoriel vous expliquant comment créer un serveur web en quelques lignes de code.
N'ayant jamais vraiment compris l’intérêt de commencer par cette étape, nous allons procéder autrement pour vous faire comprendre (un bout de) ce que permet cette solution, qui a révolutionné le petit monde de JavaScript il y a presque 10 ans.
Pour tout dire, l’exemple choisi sera sans doute considéré comme le pire croisement de choix possible pour un développeur en 2018. Mais après tout, la beauté du développement logiciel et la liberté donnée par un langage tel que JavaScript, c’est aussi ça.
Node.js, c’est quoi ?
Commençons par quelques bases. JavaScript est un langage qui s’exécute côté client. Il est interprété par votre machine, le plus souvent via votre navigateur, et non côté serveur comme c’est le cas pour PHP.
Créé en 1995 par Brendan Eich, il a fortement évolué depuis et a même été standardisé dès 1997 sous la forme d’ECMAScript. Il est simple à prendre en main, dispose de grandes possibilités, mais surtout d’une très large communauté tant il est au centre du web actuel.
Il a été pensé pour s’exécuter au sein d’une page web pour la rendre dynamique, et pas comme un langage de script à part entière tel que Python, Ruby ou PowerShell. Pour cela, il lui manquait un environnement d’exécution (ou runtime). C’est ce que lui a apporté Node.js.
Cette plateforme open source se base sur le moteur V8 de Chrome/Chromium. Mais plutôt que de le mettre à disposition d’un navigateur côté client, il permet une exécution au sein de n’importe quelle machine et donc côté serveur. Le tout, avec une architecture orientée évènements, capable de gérer un grand nombre d’accès asynchrones en simultané.
Vous pouvez donc faire fonctionner un programme JavaScript comme n’importe quelle autre application. Comme nous allons le voir, il est même possible de le compiler désormais, pour l’utiliser de manière indépendante dans différents systèmes d’exploitation. Mais pas sans quelques sacrifices.
Un IDE et c’est parti !
La première chose à faire pour commencer à exploiter Node.js est de l’installer sur votre machine. Deux branches sont disponibles : Current (10.x actuellement), avec toutes les dernières fonctionnalités, et LTS (8.x actuellement) qui se veut stable et suivie à long terme. Nous opterons pour cette dernière.
Des binaires sont disponibles pour Linux (ARM et x86), macOS ou Windows, ainsi que des plateformes moins courantes comme SunOS. Une image Docker est également fournie.
Une fois l’installation terminée, il nous faut un éditeur pour créer notre première application. Nous utiliserons Visual Studio Code, mais vous pouvez choisir ce que bon vous semble. Nous vous conseillons tout de même un IDE qui dispose d’outils pensés pour les développeurs et d’un terminal. Atom peut être une bonne alternative.
Une fois dans l’interface, créons un fichier hello.js
pour y taper la ligne suivante :
console.log("Hello, world !");
Une fois le fichier enregistré, il suffit de l’exécuter. Rendez-vous dans le terminal (CTRL+ù), dans le dossier où se situe le fichier, et lancez la commande suivante :
node hello.js
Le résultat devrait simplement afficher le texte « Hello, world ! » et revenir à la console :
C’est quand les vacances ?
Procédons maintenant à un essai un peu plus complexe : afficher le temps restant avant les vacances, en partant du principe qu'elles débutent le 15 juillet 2018.
Commençons par créer trois constantes : une contenant la date de nos vacances, une autre la date du jour et une dernière le délai entre les deux. Une fois leur valeur récupérée, elle sera affichée :
const dateVacances = new Date('2018-07-15');
const dateAjd = new Date();
const timeZone = dateAjd.getTimezoneOffset();
const delai = dateVacances - dateAjd +(timeZone * 60 * 1000);
console.log(dateVacances);
console.log(dateAjd);
console.log(delai);
Il suffit là encore de tester le résultat dans la console de notre IDE via la commande node hello.js
. Par défaut, le délai entre deux dates est renvoyé sous forme d'une valeur en millisecondes. On y ajoute le décalage horaire issu de la zone géographique qui est, elle, renvoyée sous forme d'une valeur en minutes.
Pour obtenir un résultat plus présentable, il nous faut calculer le nombre de jours, de semaines et de mois qui nous séparent de la date fatidique. Pour cela, nous allons ajouter la portion de code suivante :
const jours = Math.round(delai / 1000 / 3600 / 24);
const semaines = Math.round(delai / 1000 / 3600 / 24 / 7 * 10) / 10;
const mois = Math.round(delai / 1000 / 3600 / 24 / 365 * 12 * 10) / 10;
console.log(jours);
console.log(semaines);
console.log(mois);
Via la méthode
, nous obtenons des arrondis sous forme d’un entier. Pour obtenir un résultat à une décimale près, nous multiplions la valeur par dix avant de la diviser par dix une fois l’arrondi calculé.Math.round()
Nous pouvons désormais afficher notre résultat sous forme d’une phrase avec la ligne suivante :
console.log(`J-${jours} avant les vacances, soit ${semaines} semaines ou ${mois} mois`);
Cette méthode un peu simpliste a néanmoins quelques effets négatifs : si la date est passée, une valeur négative sera affichée, le pluriel n’est pas pris en compte, ainsi que les cas de dates proches de celle de nos vacances.
Nous allons donc définir trois cas spécifiques via des phrases prêtes à utiliser :
const stringTropTard ="Le début des vacances, c'était avant !";
const stringAjd ="Le début des vacances, c'est maintenant !";
const stringDemain ="Le début des vacances, c'est demain !";
Nous établissons également une série de règles pour définir la phrase finale, affichée une fois la situation analysée :
let stringFinale;
if (jours <- 1) stringFinale = stringTropTard;
else if (delai < 0) stringFinale = stringAjd;
else if (jours < 2) stringFinale = stringDemain;
else
{
stringFinale =`J-${jours} avant les vacances`;
if (semaines >= 2 || mois >= 2) stringFinale +=", soit ";
if (semaines >= 2) stringFinale +=`${semaines} semaines`;
if (semaines >= 2 && mois >= 2) stringFinale +=" ou ";
if (mois >= 2) stringFinale +=`${mois} mois`;
stringFinale +=" !";
}
console.log(stringFinale);
Ici, notez l’utilisation du mot-clé let
plutôt que const
pour la variable stringFinale
. La raison est simple : sa valeur va être modifiée. On évite également la question du pluriel en ne prenant en compte le nombre de jours ou de semaines que si leur valeur est supérieure à 2.
On peut désormais nettoyer notre code en supprimant toutes les lignes contenant la méthode console.log()
, excepté la dernière qui affiche le résultat final. On peut aussi commenter ces lignes afin de pouvoir les réutiliser plus tard si nécessaire.
Et si on rendait le tout indépendant ? Merci npm et pkg
Notre petite application fonctionne bien dans un terminal, sur n’importe quelle plateforme. Mais pour l’exploiter il faut que Node.js soit installé, ce qui n’est pas simple pour la distribution et l'utilisation par un tiers.
Il nous faut alors créer un package intégrant l'environnement d'exécution. Il n’existe pas d’outil livré avec Node.js pour cette action, mais d'autres permettent de le faire. C’est notamment le cas de pkg, diffusé sous licence MIT et encore développé aujourd’hui. Son installation est simple grâce au gestionnaire de paquets de Node.js : npm.
Il suffit de taper la commande suivante dans le terminal de l’IDE :
npm install -g pkg
Les fichiers nécessaires seront téléchargés et installés, vous n’aurez ainsi plus qu’une ligne de commande à taper pour créer une version Linux, macOS et Windows :
pkg hellos.js
Trois fichiers sont créés : hello-linux
, hello-macos
et hello-win.exe
. Les deux premiers pèsent à peu près 35 Mo, 22 Mo pour le dernier… contre 1 ko pour le fichier de départ. L’environnement d’exécution intégré occupe en effet un minimum de place et ne permet pas d'obtenir un fichier plus compact.
On notera également que le résultat n’est pas affiché de manière instantanée, ce qui montre une certaine « lourdeur » par rapport à une application compilée, exploitant C++/C# par exemple.
Développons une application multiplateforme, basée sur JavaScript, Node.js et pkg
-
Node.js, c’est quoi ?
-
Un IDE et c’est parti !
-
C’est quand les vacances ?
-
Et si on rendait le tout indépendant ? Merci npm et pkg
Commentaires (49)
Vous devez être abonné pour pouvoir commenter.
Déjà abonné ? Se connecter
Abonnez-vousLe 26/06/2018 à 09h03
35 Mo pour un simple “Hello World”, et après on s’étonne des pages webs lourdes et certains osent dire que javascript c’est l’avenir.
Sans moi.
Le 26/06/2018 à 09h09
C’était un peu le principe de montrer la limite. Après ça reste une solution assez simple pour packager une app facile à développer en multiplateforme ;)
Le 26/06/2018 à 09h10
On ne parles pas forcément de “pages web” mais “d’applications natives”, ce qui “excuse en partie” le fait que le framework ET l’environnement d’exécution soit embarqué.
Pour les pages web, pas besoin d’embarquer node.js, le navigateur intégré fait l’affaire, et le fichier .js suffit :) soit 1ko! Après libre au dev de connaitres les limites des technos :)
Personnellement j’ai énormément de mal avec Node.js, d’autres technologies tels que xamarin permettent la même chose, en étant beaucoup plus léger (bien que relativement lourds vis à vis d’une vrai app native).
Le 26/06/2018 à 09h17
C’est justement le petit problème que j’ai avec Javascript, à la base c’était un langage pour faire des trucs rigolo sur des pages web, puis c’est devenu plus sérieux, mais encore limité aux web, à présent, on veut tout lui faire faire, mais je n’ai pas l’impression que c’est vraiment prévu pour à la base.
Pour les applications tout intégrées, c’est plus simple à déployer, mais si la parti “outils intégrés” permettant à l’application représente 99% du la taille du programme, ça pose quand même question.
Intéressant pour le style, pas plus.
Le 26/06/2018 à 09h21
Le 26/06/2018 à 09h28
Pour les 99% du programme c’est un faux débat. Cette partie est fixe donc évidemment pour un hello world ça pique un peu mais c’est pas vraiment l’objectif de ce genre de framework.
Pour l’utilisation du JS je suis plus emmerdé par la manque de cohérence dans la plupart des cas avec le reste du système.
Le 26/06/2018 à 09h28
Javascript à su énormément évoluer (comparativement à VBScript ayant un temps eu la même fonction, mais qui est mort et enterré au profit de powershell qui s’est cantonné au scripting shell)
Ce n’est plus le petit langage de scripting pour apprendre sur une page web, c’est un langage qui actuellement possède beaucoup d’atouts vis à vis d’autres langages plus évolués (Class, Prototyping, Closures, etc)
En revanche, ce qui me “gène” dans node.js c’est la lourdeur de l’environnement d’exécution en effet… Mais comme le dit à juste titre EMegamanu, Réponse différente pour un besoin différent.
Le 26/06/2018 à 09h57
Oui, c’est ce que je voulais dire, ça la parti “outils” de ton programme tout compris prendre peu de place ça a plus d’intérêt.
Le 26/06/2018 à 10h23
Le 26/06/2018 à 10h23
Prochaine étape: ReasonML ? 😇
Le 26/06/2018 à 10h30
Je suis à deux doigts de faire un tuto Windev là " />
Le 26/06/2018 à 10h32
Est-il possible de faire un sondage sur le % de dev (et sous quelle language) de la commu NextInpact ? " />
Le 26/06/2018 à 10h33
Le 26/06/2018 à 13h21
Le 26/06/2018 à 13h39
Que de la bouche " />
Le 26/06/2018 à 14h39
Le 26/06/2018 à 14h50
Le 26/06/2018 à 14h54
Le 26/06/2018 à 15h38
Oui, c’est même un peu le sujet de l’article ;) Après pour afficher une phrase dans une interface graphique (comme demandé), ça peut être une solution.
PS : les trois projets évoqués ne sont plus vraiment maintenus ;)
Le 26/06/2018 à 16h15
Le 26/06/2018 à 16h17
Typescript?
Le 26/06/2018 à 16h20
Ben oui, je trouve que typescript est un super langage, sa plus grande faiblesse c’est qu’au runtime ça reste du javascript donc toutes les erreurs de typages peuvent “leaker” malgré tout.
Le 26/06/2018 à 16h32
Je suis pas spécialiste en compilateurs, mais je ne vois pas trop la différence avec un langage typé classique comme le C par exemple : le compilo vérifie le typage, et te fait une erreur s’il n’est pas cohérent.
Si le compilo en laisse passer une (parce qu’il est boggé ou parce que tu fais des cast manuels comme un gros dégueulasse), tu auras le même type de problème à l’exécution.
Le 26/06/2018 à 16h52
Je suis d’accord tu peux faire des cast dégueulasses en C, mais ce genre
de choses se voit dans le code. Le comportement par défaut est safe, si
tu veux être unsafe tu dois le rendre explicite => pour moi c’est la
bonne façon d’appréhender les choses.
Typescript règle une
bonne partie des problèmes du javascript mais malheureusement pas tout. Un exemple simple: tu récupères du JSON d’un appel HTTP. Ce json va être désérialisé avec quelque chose du genre JSON.parse . Là, avec typescript tu définis le type de l’objet reçu. Tu n’as aucune garantie à la compilation que le json matche le type indiqué. Si ça pète ce sera au runtime. Tu me diras, c’est exactement pareil avec n’importe quel langage quand on parse du texte. Sauf qu’avec un autre langage, c’est à la déserialisation que ça va échouer, donc immédiatement (donc “fail fast”) tandis qu’avec typescript, le compilo a beau avoir les informations de typage, au runtime (JS) il n’y en a plus aucune donc JS/TS ne peut pas reporter d’erreur rapidement, ce qui fait que l’erreur risque de se propager bien plus loin dans les appels et sera potentiellement beaucoup plus difficile à détecter. (il y a des libs qui existent pour ce genre de chose, comme “typecheck” si mes souvenirs sont bons, mais assez relou à utiliser).
Ça peut paraître lointain ce genre de préoccupation mais perso je l’ai vue et revue cette situation.
Sinon y’a aussi le fait que pour s’interfacer avec bon nombre de libs JS il faut encore utiliser du “any” à tout bout de champ (donc l’intérêt de typescript s’envole).
Le 26/06/2018 à 17h36
Aaaahh node.js…la première fois que je l’avais vu mentionné, c’était dans un blogpost décrivant l’architecture de Trello.
Je me disais que c’était un jouet à l’époque (“du javascript server side, sérieux?!”), mais finalement ça tient toujours et c’est quand même très répandu.
L’ironie dans tout ça, c’est que les frameworks javascript “client” (type backbone.js, mentionné dans le blog) deviennent eux has-been au bout d’un ou deux ans…
Le 26/06/2018 à 18h06
A noter que tu pouvais très bien faire du JavaScript serveur il y a plus de dix ans avec Rhino ou même avec de l’ASP classique. :p
Le 26/06/2018 à 18h47
Je m’excuse un peu pour la pub mais je pense que ça peutservir pour défendre Node et les applications standalone
Je dév et gère un projet d’app standalone qui tourne en NodeJS et qu’on peut installer partout, avec PKG justement.
Le truc étant qu’au vu de mes besoins, NodeJS était juste le plus adapté. Les gens ont souvent des a priori négatifs sur tel ou tel langage parce que “lol c’est vieux” ou “lol c’est nul, regarde python c’est mieux” (remplacez python par tout autre langage de votre choix).
Or il se trouve que Node a permis de faire un développement très rapide, crossplateforme et surtout sans avoir à réinventer la roue pour chaque composant, petit ou gros. Un serveur web simple ? J’ai. Un moyen de piloter le lecteur vidéo mpv ? J’ai. Un moyen de parcourir des fichiers de sous-titrage en .ass ? J’ai. Une base de données qu’on peut embarquer, genre SQLite ? J’ai. Un moyen de lire les tags ID3 des mp3 ? Pas de problème.
Et ça donne un truc comme Karaoke Mugen : Karaoke Mugen
J’ai parlé de la façon dont ça a été développé et des choix techniques et d’organisation qui ont été faits, si y’a des intéressés : Meido Rando
Node c’est peut-être pas la solution idéale pour tout, mais ça fait le taff dans pas mal de cas. Le logiciel que j’ai linké plus haut, il a tout juste un an. C’est fou tout ce qu’on peut faire en un an de developpement sur son temps libre aujourd’hui :p
Le 26/06/2018 à 19h07
L’avantage de node et l’écosystème npm c’est aussi qu’il y a pléthore de modules spécifiques en c++/assembleur/ce-que-vous-aimez et utilisables facilement derrière.
Le 26/06/2018 à 19h10
Node, c’est sympa, mais il faut un ssd, un repertoire node_modules sur un projet un peu complexe, c’est facile 23 000 petit fichiers, C’est comme maven, ça télécharge internet " />
Le 26/06/2018 à 19h18
Typescript a été inventé pour attirer les développeurs java" />, on retrouve les classes, les constructeurs, tout ce qui fait le charme d’un vrai langage, et ensuite c’est le transpileur qui transpire et transforme le typescript en JavaScript
Le 27/06/2018 à 09h17
Le 27/06/2018 à 11h57
Le 27/06/2018 à 12h51
Le 26/06/2018 à 10h34
Le 26/06/2018 à 10h44
Site internet avec Windev = 350Mo, la ou on as 10 pauvres pages ^^
Pour les applis et les services en revanche… ca va encore, plus léger pour un hello world que node.js (c’est ensuite que ça se gâte…), et pour le mobile j’ai été assez surpris de la légereté des packages (et des fonctionnalités :p)
Mais sincèrement entre Node.js et Windev….euh…. mon coeur balance
N’empèche…. chiche de faire le même tuto en WD?
Le 26/06/2018 à 10h46
Tout dépends de ce qu’on dev…
Et tout dépends de l’infra! c’est compliqué ce genre de sondage, sur developpez.com ils le font, mais c’est jamais vraiment représentatif…
Le 26/06/2018 à 11h14
J’utilise PHP, Javascript et de plus en plus souvent Java (pour une API Rest).
PHP devient de plus en génial (version 7.2), Java reste lourd mais puissant et puis il y a Javascript.
On peut faire ce qu’on veut en Javacript et JSON est devenu LE moyen d’encapsuler les données. NodeJS apporte une couche serveur pratique et qu’on le veuille ou non, Javascript est maintenant partout, on ne parle plus de site web mais d’application web.
Pourtant, j’ai quelques réserves sur NodeJS. Pas sur la plateforme en elle-même mais plutôt sur les librairies qu’on peut y installer. C’est très dépendant du suivi de la communauté et de quelques développeurs. Vous installez un paquet via npm aujourd’hui, il sera peut-être obsolète et non maintenu demain. Et en plus de ça, ça vous installe une tonne de dépendances sur lesquelles vous avez un contrôle très relatif.
Et comme ça évolue à une vitesse quasi-supraluminique, la maintenabilité des projets est parfois très compliquée.
Donc c’est bien mais pas si bien que ça…
Le 26/06/2018 à 11h20
J’aime bien node.js pour le système de package associé : npm (qui est un peu sous exploité dans cet article, imo)
J’arrive à faire des petits développement sous linux rapidement avec node.js, une vingtainede ligne de code, trois package installés avec npm, et j’ai une application qui vérifi les annonces leboncoin et m’envoi un SMS quand il y en a une nouvelle, le tout en enregistrant les informations dans une BDD.
Après, j’ai choisi node.js car je connaissais le language, c’est surement possible de faire ça avec d’autres.
Puis bon, on va éviter de mentionner electron à ceux qui critiquent la lourdeur de la chose :)
Le 26/06/2018 à 11h23
Oui, mais le problème est le même pour les autres, la gestion des dépendances n’étant pas arrivée avec node.js (et les abandons de projets non plus).
Mais bon, pour du “devops” d’applications d’appoint, je pense qu’on peut trouver un intérêt.
Le 26/06/2018 à 11h35
Je ne suis pas d’accord, Java et PHP pour reprendre mes exemples, sont maintenus par des sociétés telles que Oracle et Zend. Tu as quand même plus de garantie de rétrocompatibilité (point faible de Java d’ailleurs).
Le 26/06/2018 à 11h56
Ah, de la programmation fonctionnelle, j’ai une érection et la larme à l’œil, là !
Le 26/06/2018 à 12h16
C’est vrai qu’il aurait du utiliser du C voire de l’assembleur pour ce Hello World. Pas un byte ne devrait dépasser.
C’est vrai qu’il aurait du faire un backend entier pour un tutoriel de débutant.
C’est vrai qu’il aurait du faire des pipelines CI/CD pour mettre en ligne ce Hello World.
C’est vrai qu’il aurait du monter un cluster Kubernetes sur GCP pour ce Hello World.
C’est vrai qu’il aurait du faire un tutoriel avec un langage largement mieux.
C’est vrai qu’il aurait du faire un tutoriel avec tout les langages possibles et imaginables pour contenter tout le monde.
… Pour une liste exhaustive voyez les coms avant et après.
Le 26/06/2018 à 12h25
Le 26/06/2018 à 12h35
Et sinon histoire d’être pointilleux, il ne manquerait pas la déclaration de “dateAjd” ?
Le 26/06/2018 à 12h43
Il faut pas mélanger un langage (JavaScript), un environnement d’exécution (NodeJS) et un gestionnaire de dépendances (npm).
JavaScript n’inclut que très peu de BC par rapport à PHP (même si ce dernier en inclus peu aussi). Les 2 permettent de gérer sans trop s’embêter la compatibilité ascendante.
NodeJS, de mémoire, le dernier BC a nécessité de recompiler des modules NodeJS. Et cela a été fais lors d’un changement de version LTS. Le reste du temps, ça bouge peu.
Le problème de JavaScript est principalement dû à son côté client où c’est plus compliqué de gérer les fonctionnalités disponibles (version de navigateur…). Les transpileurs permettent de compenser ça même si ça chie du code moins optimisé.
Le 26/06/2018 à 12h44
Le 26/06/2018 à 12h47
Enorme David! Merci surtout ! Me tarde déjà de voir la suite (probablement une petite interface graphique et/ou qt ? )
Le 26/06/2018 à 12h56
Si on parle bien des librairies (en termine de composant additionnel) ici, le problème est le même sur PHP/Java.
Il n’y a aucune garantie que les librairies PHP (obtenu grâce à composer) soient maintenu dans le temps.
A moins que tu parles des composants déjà disponible dans PHP (mysqlnd ? pdo ? memcached ? etc.), alors là je suis d’accord, mais ça amène aussi moins de flexibilité dans leur utilisation/amélioration.
Le 26/06/2018 à 13h20