react native expo android ios stack navigator Cours web Mobile – React Native

Chap 0 : Présentation de ReactNative & Expo

Vous commencez le développement mobile et vous hésitez à choisir ReactNative ou la surcouche Expo ? Je vous donne quelques indices afin d’y voir plus clair sur quel framework vous devriez choisir en fonction de vos compétences, du temps, et de vos besoins.

Code source du projet est disponible ici, sur Github.

Présentation de React

Framework pour le développement web frontend, développé par Facebook et concurrent direct de Angular et de Vue.js.

 

Dom Réel et virtuel

React est à la mode. Il est performant, et ce grave à un point important, est qu’il utilise un DOM (Document Object Model) virtuel.

Le DOM (réel) est l’arbre de nœuds, la représentation textuelle de toute votre application web. Quand vous effectuez un changement d’état au sein de votre application, l’intégralité du DOM est recréer. Cela comprend alors l’ensembles des éléments fils de l’application. Et ceci peut être couteux en terme de performance pour des applications grandissantes, surtout si vous y effectuez des modifications fréquentes de votre UI.

Le DOM virtuel quand à lui est un second arbre, correspondant à l’état réel de la globalité de votre application. Vous pouvez alors vous demandez, n’est-ce pas doublon d’avoir deux arbres à l’identique ? Et bien non.

On imagine que vous effectuiez une modification de couleur, sur un texte par exemple. Dans le cas d’une application avec Angular, celui-ci va redessiner la globalité de l’application. Avec React, seul le DOM virtuel va être modifié. React va alors réaliser une comparaison avec des algorithmes spécifiques entre le DOM virtuel fraichement actualisé, et le DOM réel. En fonction des différences entre les deux arbres, seul les nœuds qui ont un nouvel état, vont être redessiner dans le DOM réel. Cela permet de redessiner seulement un seul nœud, dans notre exemple.

Voici une image plus parlante :

virutal dom vs real dom

 

Présentation de React Native (Vanilla)

C’est un framework développé par Facebook pour le développement d’applications cross-platform (iOS et Android).

 

Développement natif vs développement hybride

Le développement natif est l’utilisation de SDK spécifique. Xcode pour iOS, et Android studio pour Android.

 

Pourquoi favoriser le dév. natif
  • Le développement natif utilise ses modules et bibliothèques natives, avec son langage natif. Il sera toujours plus performant que les solutions hybrides, même si au cours du temps nous observons de moins en moins de différences
  • L’accès aux modules spécifique facile (notification push par exemple)
  • Poids des apk/ipa très léger

 

Pourquoi favoriser le dév. hybride
  • Un seul langage de développement pour deux plateformes
  • Un code unique. Donc 2x moins de bug, en 2x moins de temps
  • Une interface UI/UX identique, évitant des différences

Présentation de Expo

Expo embarque ReactNative, c’est une sorte de wrapper, de surcouche. Vous retrouvez donc l’ensemble des items graphiques de ReactNative.

En voici les principales caractéristiques :

Projet déjà configuré ! En une minute vous avez votre Helloworld de fonctionnel ! Cela évite des paramétrages en tout genre et fastidieux sous ReactNative Vanilla pour paramétrer Xcode et AndroidStudio.

Pas besoin de mac pour tester votre app sur les deux OS mobile ! Et ça, ça fait plaisir. Ayant un vielle Iphone et mon Android de tout les jours, je peux tester via l’application Expo (disponible sur les stores iOS et Play), avec hot-reload, et sans avoir de Mac, l’application que je développe sur mes deux smartphones. Même si le dév. hybride promet d’avoir un UI/UX 100% identique entre les deux plateformes, il m’est arrivé que mes checkbox ne s’affichait pas correctement sur iOS. J’ai donc forcé pour mes deux plateforme, l’utilisation de la checkbox Android. Soucis auquel je me serais rendu compte une fois seulement uploadé sur les stores. Sous ReactNative Vanilla, vous pouvez seulement tester sur votre iOS si vous tournez sous macOS,  et seulement sur votre Android si vous êtes sur Windows pour développer.

Pas besoin de mac pour builder votre app ! Vous pouvez utiliser les serveurs expo pour cela. Attention, il vous faudra obligatoirement un compte développeur chez les deux sociétés, et acheter la licence qui va avec. Autre piège, votre build se fera à distance et non en local, attention donc si vous développer une app qui doit rester à l’abris des regards.. Mais dans tout les cas si vous souhaitez build en local et sans mac, vous pouvez utiliser une VM sous macOS Catalina avec QEMU/KVM sans soucis. Sous ReactNative Vanilla il vous faudra forcement les deux OS pour builder sur les deux plateformes, mais qui se résous aussi bien par la VM.

Accès à l’ensemble des modules natifs compliqué voir impossible… A un moment donnée, votre application grandissante va prendre en fonctionnalités. Etant donnée que Expo est une surcouche, l’accès aux modules natifs n’est pas possible pour réaliser certaines fonctionnalités. Je prends comme exemple connu comme les notifications push, ou achats-in app. Vous n’y aurez simplement pas accès.

… mais vous pouvez Ejecter Expo ! Vous pouvez cependant ‘éjecter’ Expo pour palier au problème précédent. Mais à en lire certaines expériences sur le net, selon la taille et le versionning de votre projet, que ça puisse très bien se passer comme mal se passer.

Poids supérieur des apk/ipa ! J’ai publié sur les stores ma première application avec des fonctionnalités très simple. Elle fait 50mo à télécharger sur les stores.

 

Quel framework choisir au final ?

  • Vous débutez sur le développement mobile ?
    • Oui ? Foncez sur ReactNative + Expo

 

  • Votre application requiert des accès natifs à des modules particuliers (achats in-apps ou push-notifications) ?
    • Oui ? : Foncez sur ReactNative vanilla
    • Non ? : Foncez ReactNative + Expo

 

Si votre choix se confirme à développer sous Expo, je vous propose de commencer par le premier chapitre, afin d’installer l’environnement de développement. Hello World sur mon smartphone en moins d’une minute garantie ! 😉

react native expo android ios sqlite Cours web Mobile – React Native

Chap 6 : Stockage de données complexes (SQLite)

Nous avons vu dans le chapitre précédent comment stocker en local des données simples.

On va s’attarder cette fois-ci à comment stocker des informations plus nombreuses, plus complexes et ce de façon plus ordonnée, en utilisant des bases de données SQL.

On va réaliser une simple to-do app, avec possibilité d’ajouter une note, ou d’en supprimer, avec une liste permettant de toute les afficher.

 

Code source du chapitre disponible sur Github.

 

On ne peut utiliser n’importe quel outils pour persister des données car nous sommes sur un projet Expo, nous empêchant d’accéder aux modules natifs de iOS et Android. SQLite est un moyen fonctionnant avec des projets Expo.

 

Objectifs

  • Stocker localement des informations via une base de donnée SQL

 

react native sqlite

 

Prérequis

Installez le package pour utiliser SQLite :

expo install expo-sqlite

 

Nous l’importerons dans nos fichiers de la manière suivante :

import * as SQLite from 'expo-sqlite';

Base de données & CRUD

CRUD : diminutif correspondant aux requêtes basique, à savoir Create, Read, Update et Delete.

Création de la base de données

Rien de plus simple, une seule ligne suffit :

On donne un nom à notre base, en argument. Celle-ci n’est crée qu’une seule et unique fois. Si on rappelle cette même méthode, on récupère la base de donnée crée auparavant, aucun risque de doublon.

 

Création de la table NOTE

On va maintenant créer notre table. Je vous montre la façon la plus simple de réaliser des transaction SQL vers notre base :

Requête SQL des plus basique avec le mot clé CREATE TABLE. On lui donne un nom de table, ainsi que la définitions de nos colonnes. Un ID auto-incrémenté pour garantir l’unicité de nos données, ainsi qu’un attribut TEXT qui contiendra le contenu de nos notes.

Nos deux attributs ne peuvent être null, et on leur défini un type, soit Text ou Integer.

 

Optimiser les requêtes

Je préfère une autre annotation que la précédente pour questionner la base de données, récupérer nos objets et leurs affecter des transformations. Je trouve plus clair et simple à l’utilisation. On définit notre modèle de requête avec une promesse :

On pourra utiliser ce modèle dans des fonctions async, via un appel par un await. On pourra utiliser des then() et catch() à l’appel du service dans nos vues, permettant par exemple d’afficher à l’utilisateur dans une popup si une note à bien été ajouté ou si dans le cas inverse afficher un message d’erreur avec son origine.

 

Récupérer toute les notes

On définit une interface pour les objets que l’on va récupérer en base. Cela nous facilitera leurs manipulations au sein de notre application :

 

On fait appel à notre modèle pour questionner la base :

On récupère nos objets via la requête. On va itérer sur notre résultat de requête pour re-typer correctement nos objets.

 

Ajouter une note

Seule différence, on va ici passer en argument le contenu de ma note que l’on souhaite persister en base. Pas besoin de lui passer un ID pour la note, car celle-ci est généré automatiquement en base. Nous avons défini cette option tout à l’heure, lors de la création de la table.

Supprimer une note

Quasiment identique au point précédent, sauf qu’ici on lui passe un ID de note à notre fonction, étant donné que c’est l’attribut qui défini l’unicité de mes items dans ma table NOTE :

 

Récupération des items dans la vue

Nous venons de créer notre base ainsi que des opérations CRUD permettant d’interagir avec elle. On va désormais créer une nouvelle vue, avec un champ de texte permettant de donner du contenu à une note, un bouton pour ajouter cette note, une liste scrollable permettant de naviguer sur l’ensemble de nos notes en base, et leur associé à chacun un bouton pour les supprimer.

 

Définition du state de notre vue

On commence par créer le squelette de base de notre vue :

On utilise ici un composant de classe et non un composant fonctionnel. On a besoin d’utiliser un state pour l’affichage dynamique du contenu de notre liste scrollable. On défini un attribut myNoteList correspondant à une liste de l’ensemble de nos notes en base, ainsi qu’un second attribut note correspondant au champ de texte remplissable par l’utilisateur pour créer une nouvelle note. On initialise les deux attributs dans le constructeur.

 

Définition des méthodes de notre vue

On défini les méthodes pour mettre à jour nos éléments, pour ajouter une note, ainsi que la supprimer :

La méthode componentDidMount() est une méthode standardisé de React, permettant d’être appelé une seule et unique fois et ce à la fin de la création du composant. On lui demande à l’ouverture de notre page, d’initialiser notre liste avec le contenu de notre base de données.

 

Définition des éléments visuels de notre vue

Ici rien de bien complexe. J’ai créer un titre de page, un champ de texte avec un bouton pour ajouter une note. Une liste scrollable présentant l’ensemble des notes en base, ainsi qu’une option permettant de les supprimer :

J’ai utilisé des icones Ionicons inclus dans Expo, qui s’adapte en fonction de si vous êtes sur Android ou iOS via la méthode Platform.OS, encapsulé dans des TouchableOpacity, pour rendre un peu plus esthétique mes boutons d’interactions, ainsi que des flexbox pour avoir une touche de responsive design.

 

Conclusion

Vous venez de voir comment créer très simplement une base de donnée pour votre application React Native tournant sous Expo, comment l’interroger et surtout comment récupérer et afficher le résultats dans une belle vue responsive.

react native expo android ios async storage Cours web Mobile – React Native

Chap 5 : Stockage de données simples (AsyncStorage)

Nous venons de voir au chapitre précédent comment organiser une navigation complexe et imbriquée pour une application avec une architecture grandissante.

Nous allons voir aujourd’hui comment stocker des données plutôt simple, par exemple des paramètres de l’application comme l’activation ou non d’un thème clair ou sombre.

 

On ne peut utiliser n’importe quel outils pour persister des données car nous sommes sur un projet Expo, nous empêchant d’accéder aux modules natifs de iOS et Android. AsyncStorage est un moyen fonctionnant avec des projets Expo.

 

Code source du chapitre disponible sur Github.
 

 

Objectifs

  • Stocker localement des informations via JSON

async storage chap 5

 

Prérequis

Installez le packet requis via une console :

expo install @react-native-async-storage/async-storage

Utilisez l’import qui correspond dans vos fichiers :

import AsyncStorage from '@react-native-async-storage/async-storage';

Que-ce que AsyncStorage

AsyncStorage nous permet de persister des données en local sur le smartphone, de façon asynchrone et non crypté. Les informations sont sauvegardé en clair, donc éviter de stocker des données sensibles tel que des mots de passes.

Le stockage s’effectue sous forme de couple tel quel : <Clé, Valeur>.

On ne peut stocker que des string, donc pour des éléments plus complexe tel que des objets, on devra utiliser JSON.stringify() pour la conversion en JSON lors de la sauvegarde d’une donnée, et utiliser JSON.parse() pour lire un objet.

Sauvegarder des données

Pour un string

Pour un objet

 

Lire des données

Pour un string

Pour un objet

 

En pratique

On va faire un exemple tout bête, à savoir charger le nom d’un utilisateur à l’appui d’un bouton.

 

Méthode d’écriture & lecture de donnée

On commence par définir nos deux méthodes pour charger et sauvegarder une donnée :

On appellera la méthode initProfileName() dans l’entrée de notre l’application (App.tsx) pour initialiser notre donnée.

 

Mise à jour de notre vue

On crée un état initialisé à ‘Invité’. On aura une méthode appelant notre fonction pour lire notre donnée via AsyncStorage, définit précédemment. Et enfin une méthode render() pour afficher un champ de texte, et un bouton bindé avec la fonction de chargement de notre donnée locale :

 

Conclusion

On vient de voir comment stocker des informations simple en local. Nous allons voir au prochain chapitre comment stocker des informations plus complexe et surtout en quantités plus importantes.

 

react native expo android ios tab navigator Cours web Mobile – React Native

Chap 3 : Tab navigator, police d’écriture, status bar…

On va vu dans le chapitre 1 comment afficher un HelloWorld!, puis dans le chapitre 2 comment générer nos installeurs. Maintenant que l’on est capable d’utiliser notre application du code à notre smartphone, on va commencer le développement.

react native chap 3 bottom tab bar navigation

 

Objectif

  • Initialiser une petite architecture
  • Créer plusieurs écrans en affichant un titre différent
  • Créer une barre de navigation qui switch entre elles

 

Code source du chapitre disponible sur Github.
 

 

Définition de l’architecture

On va devoir commencer à réfléchir à la structure de notre projet. En effet, nous codions toute l’app dans le même fichier auparavant. On va ajouter cette fois ci de nouveaux composants, et ça risquerai de faire plutôt brouillon par la suite de notre tutoriel. Je vous propose celle-ci :

 

squelette de base application react native

Voici un squelette de base que j’utilise couramment pour débuter une application ReactNative. Quelques explications concernant leurs utilités :

– Service : dossier donnant des services à l’utilisateurs. Générer un pdf, initialiser des paramètres à l’ouverture de l’application, etc.

– Page : contient nos vues globales, affiché tel qu’elle à l’utilisateur

– Navigation : définit l’ensemble des éléments permettant de naviguer entre les vues (tab navigator, stack navigator, etc.)

– Database : contient l’ensemble des requêtes pour questionner une base de données SQL

– Shared : éléments utilisé à travers toute l’application, que ça soit des énumérations, constantes ou interfaces

– Assets : contient des images, des polices, et tout autre éléments ‘brut’ nécessaire pour remplir notre application

– Scripts : permet d’automatiser des tâches, comme le build des ipa ou apk

– Component : contient les différents composants de notre applications, avec une granularité concernant leurs tailles (Atome => Molécule => Organisme => Template )

App.tsx : Point d’entrée de notre application

App.json : fichier de configuration global de notre application

Package.json : contient l’ensemble des dépendances de notre app (paquets npm)

 

Biblio requises

Il nous faut de belles icones :

npm install --save @expo/vector-icons

Il nous faut notre lib de navigation, inclus depuis react :

npm install --save @react-navigation/bottom-tabs

Ainsi que les dépendances nécessaires :

npm install @react-navigation/native
expo install react-native-gesture-handler react-native-reanimated react-native-screens react-native-safe-area-context @react-native-community/masked-view

Définition de nos écrans

Pour chaque écrans que l’on aura besoin, nous allons juste y inclure au milieu un texte, pour démontrer que l’on change bien d’écrans en naviguant. Je créer des interface minimaliste avec le code suivant :

Je le fais à l’identique pour mes deux autres écrans. Tout se passe dans le dossier /scenes/.

 

Définition de notre barre de navigation

  1. Premièrement, on définit via la méthode  createBottomTabNavigator(), une instance
  2. On export le type MainTabNavigator()
  3. On créer un <NavigationContainer>
  4. On créer <Tab.Navigator>
  5. Dans ce dernier on définit autant de <Tab.Screen> que nous souhaitons d’écrans. On lui fourni un nom, et un composant à afficher. Rappelez vous, ce sont les écrans définit précédemment via <View>

Le tabBarOptions nous permet de définir une couleur différente selon l’onglet qui est actuellement ouvert.

 

 

Ajout d’icone

Afin de rendre notre barre plus jolie, on va y ajouter des icones au dessus de nos écritures. Pour cela on va ajouter une nouvelles propriétés à la suite de tabBarOptions, dans le Tab.Navigator :

La propriété route nous permet d’assigner la bonne icone à la bonne page.

La propriété Platform.OS nous permet de savoir si nous sommes sur un iOS ou Android, permettant d’assigner la bonne icones selon les codes de bonne conduite UI/UX de chaque constructeur.

 

 

Ajouter notre tab barre au lancement de l’application

On ajoute simplement notre composant MainTabNavigator dans la fonction principale de notre App :

Soucis de superposition de status bar

Dans certains cas, il se peut que votre application déborde sur la status bar, engendrant des données au niveau de l’horloge ainsi que sur les icones de vos notifications. Pour régler ce problème, on va encapsuler notre MainTabNavigator, par une SafeAreaView :

 

Chargement local de fonts

J’ai déjà eu des soucis concernant certains texte qui étaient coupé au sein de mon application, lorsque je rendais le texte en gras. En me baladant un peu sur la toile, j’ai trouvé une petite soluce, qui consiste à charger une nouvelle font pour toute mon application, en local. Dans votre dossier Assets/, rajoutez un dossier Fonts/. Ajoutez y la police que vous souhaitez, je prends pour exemple la police Arial.

Installez le module correspondant :

expo install expo-font

 

On commence par définir nos variables dans le fichier d’entrée globale de notre application :

 

Je transforme notre composant de fonction en un composant de classe. Cela va nous permettre de définir un attribut nous permettant de savoir quand notre police sera chargé :

 

J’initialise le constructeur de la classe App :

 

On utilise la fonction componentDidMount(). Celle-ci est une routine appelé une seule fois la construction de la classe, et permet de lancer des fonctions une seule et unique fois durant tout le cycle de vie de l’application :

Elle appellera ma fonction ou je lui demande de charger ma police en local, et de mettre à jour ma variable fontsLoaded.

 

Le dernier changement consiste à laisser l’utilisateur patienter sur le splashscreen, tant que la police d’écriture n’est pas chargé. Une les assets voulu chargé, on lance notre application :

 

Faîte comme suit pour utiliser notre nouvelle police fraichement installé :

 

Conclusion

Nous venons de construire notre barre de navigation principale de notre application.

Je vous montre au prochain chapitre, comme faire de la navigation imbriqué avec des StackNavigator. Cela permettra d’ajouter autant de vue que l’on souhaite à travers nos onglets de notre barre principale.

 

android ios react native expo Cours web Mobile – React Native

Chap 2 : Builder & générer les .apk &…

Après quelques instants de build.. TADAAA !

Objectif

  • Signer son app
  • Builder offline et en local son app
  • Générer les fichiers d’installation Android (apk) & iOS (ipa)

 

Code source du chapitre disponible sur Github.
 

 

Introduction

Vous pouvez utiliser directement Expo pour lancer très facilement votre build sur leurs serveurs distants, avec la simple commande :

expo build:android

Pourquoi je ne l’utilise pas ?

Car lorsque que j’ai voulu lancer un build, leurs serveurs étaient down, laissant mon build en attente. Flemme de perdre plus de temps, je me suis lancé dans les recherches afin de savoir si l’on pouvait nous même générer notre build. C’est un peu plus tricky, mais ça marche.

 

A SAVOIR AVANT DE SE LANCER DANS LE DEV MOBILE

Je souhaite vous parler de compte développeur. ça vous évitera toute surprise comme j’ai pu avoir en développant ma première application sur les stores.

Si vous souhaitez distribuer votre application sur les stores :

  • iOS : Compte développeur nécessaire ( 100€ par an )
  • Android : Compte développeur nécessaire (25€ à vie )

Avec une licence, vous pouvez ensuite lancez autant d’application que vous le souhaitez, vous n’êtes pas limité en nombre.

 

Si vous souhaitez seulement builder votre application en local :

  • iOS : Compte développeur toujours nécessaires, sur un macOS exclusivement. Vous ne pouvez générer votre certificat, teamID et votre fichier de provision en local par vous même.
  • Android : Pas besoin de compte spécifique. Juste un macOS ou Linux d’obligatoire. Car votre fichier de clée nécessaire au build est générable en local, par vous même.

 

Prérequis

  • Bash
  • NodeJS

Build pour Android

  • macOS ou Linux ( pensez à avoir une VM )
  • JDK/JRE (Java Development kit) en version 8 exclusivement

Build pour iOS

  • macOS
  • Xcode (minimum v11.4)
  • Fastlane ( préférez l’installation par Homebrew, le plus simple et rapide moyen )

 

Si comme moi vous êtes pauvres et n’avez pas de macbook pour build votre .IPA, je vous ait fait un article qui vous sauvera un ou deux jours de recherche et de test pour avoir un macOS Catalina sur votre linux qui est proche d’avoir les performances d’une install native ! Oubliez windows, oubliez virtual box ou vmware. Même mon pc à 4000€ ne fait pas tourner macOS, car aucun de ces softs ne peut attribuer des ressources graphiques, entrainant de gros ralentissement lors de vos déplacement de souris et ouverture de logiciel. Bref, c’est inutilisable, à moins de passer par mon tuto qui utilise le combo QEMU/KVM, et qui fait tourner lui Catalina facilement sur mon portable à 2 coeurs de 2015 😁

 

On utilisera la TurtleCLI pour générer le build. Installez le via npm :

npm install -g turtle-cli

 

Signature de l’application

Android

La première étape consiste à signer l’application. Cela permet de créer des certificats concernant la sécurité, pour la distribution. On va utiliser l’outil keytool de java pour générer notre keystore :

Vous pouvez apercevoir aussi des clés avec l’extension « .keystore ». C’est une clée comme les « .jks » avec un format différent.

Cette commande va vous demander plusieurs questions vous concernant :

Génération du keystore

Un fichier va être crée. Veillez à bien mettre de côté de fichier. Il vous sera demander à chaque build de votre application

 

iOS

Il vous faudra un certificat, un apple Team ID, et un fichier de provision

 

 Génération du certificat

Allez sur votre compte développeur Apple. Dans l’onglet certificat, cliquez sur le bouton + :

apple ios generation application ipa certificat p12 provision

 

Choisissiez l’option iOS Distribution (app store and ad hoc ) :

 

Faîte continuer, et on arrive sur une nouvelle fenêtre nous invitant à envoyer un fichier CRC :

apple ios generation application ipa certificat p12 provision

 

On va devoir générer un certificat. Pour cela, lancez l’application Trousseaux d’accès qui est dans le dossier Applications/Utilitaires de votre macbook. Dans le menu en haut à gauche, cliquez sur Trousseaux d’accès, puis sur Assistant de certification, puis sur Demander un certificat à une autorité de certificat :

apple ios generation application ipa certificat p12 provision

 

Remplir les champs demandé, et faîte enregistrer en local :

apple ios generation application ipa certificat p12 provision

 

Vous aurez un nouveau fichier sur votre bureau :

apple ios generation application ipa certificat p12 provision

 

On retourne sur le compte développeur Apple ouvert précédemment, nous étions rester sur la fenêtre ou on nous demander notre fichier CSR. C’est le fichier que nous venons de générer sur le bureau que nous allons upload :

apple ios generation application ipa certificat p12 provision

 

Nous pouvons désormais télécharger notre certificat ! Téléchargez le, et ouvrez le :

apple ios generation application ipa certificat p12 provision

 

Il sera automatiquement ajouté à notre trousseau d’accès, attaché à notre session :

apple ios generation application ipa certificat p12 provision

 

Sélectionnez votre certificat fraichement installé avec sa clé privée, et exportez les deux éléments :

apple ios generation application ipa certificat p12 provision

apple ios generation application ipa certificat p12 provision

 

Exportez au format .p12, et donnez lui un nom et mettez le de côté, ce fichier vous sera obligatoire pour builder :

apple ios generation application ipa certificat p12 provision

 

Un mot de passe sera demandé, notez le bien de côté, il vous le sera demandé lors du build :

apple ios generation application ipa certificat p12 provision

 

Vous avez maintenant un certificat au format .p12 sur votre bureau. Gardez le bien de côté.

 

Création du teamID

On revient sur le compte développeur Apple, et on va allez cette fois ci dans l’onglet Identifiers, cliquez sur + :

apple team build id

 

On coche App IDs, et on continue :

apple team build id

 

 

On sélectionne App, et on continue :

apple team build id

 

 

On remplis le champ Description qui est le nom de l’application, ainsi que son bundleID sous la forme recommandé. Dans Capabilities, vous cocherez les accès et autorisations que votre application à besoin. Par exemple si c’est une application photo, elle devra avoir accès à l’APN du smartphone. Vous cliquez ensuite sur Continue, puis Register :

apple team build id

 

Notez bien votre App ID Prefix, qui est votre Team ID. Vous en aurez besoin pour build par la suite.

 

 

Fichier de provision

Troisième et dernière étape. On va maintenant s’occuper de générer du fichier de provision, lui aussi nécessaire pour buid l’application.

Toujours sur notre compte développeur Apple, on va sélectionner cette fois ci l’onglet Profiles, et cliquer sur + :

apple build ios appstore provision file

 

On sélectionne ensuite App store, dans l’onglet Distribution. A savoir, les builds Ad Hoc ne sont pas pris en charge par Expo. On clique sur Continue :

apple build ios appstore provision file

 

Sélectionnez l’app ID précédemment crée, et faîte Continue :

apple build ios appstore provision file

 

Sélectionnez le certificat précédemment crée, et faîte Continue :

apple build ios appstore provision file

 

Donnez un nom à votre fichier de provision, et faîte Generate :

apple build ios appstore provision file

 

Téléchargez le, et gardez le de côté, vous en aurez besoin pour générer votre build :

apple build ios appstore provision file

 

Export de l’application

Android & iOS

La seconde étape consiste à exporter notre application. Cela permet de créer les bundles (iOS & Android) à partir des fichiers javascript. Vous devriez apercevoir la création d’un dossier « dist » dans votre répertoire courant via la commande suivante :


Attention à utiliser la bonne, selon si votre application contient du HTTP ou HTTPS.

 

Servir l’application

Android & iOS

On va maintenant lancer notre application à partir du bundle crée précédemment, en local. Pour cela on va utiliser python. Déplacez vous dans le dossier « dist » précédemment crée, et lancer la commande suivante :

 

Vérifiez bien que le serveur tourne, via curl, ou en lançant une connexion à votre localhost via votre navigateur :

 

Build l’application

Dernière étape, on va pouvoir lancer le build de nos fichiers. Revenez à la racine de votre projet et ouvrer une autre console.

Android

Lancez la commande suivante pour lancer le build via turtle-cli :

Voilà votre fichier APK, situé dans le répertoire annoncé dans la console.

 

iOS

Lancez la commande suivante pour lancer le build via turtle-cli :

 

Soucis fréquemment rencontré

EACESS permissions denied

Vous pouvez vous confronter à des erreurs d’accès aux fichiers pour installer des packets npm globaux ( pour turtle-cli ou encore expo ). Oubliez les sudo su et sudo en tout genre, qui m’ont fait juste galérer encore plus. Vous pouvez fix cela en deux étapes :

  • Utilisez l’option ‘–unsafe-perm‘ de NPM
  • Pour le dossier ‘lib/node_modules’ qui résisterait aux erreurs, passez un coup de chown -R votreNomUser pour donner accès à votre utilisateur courant de la session au dossier en lecture et écriture.

 

Conclusion

Nous venons de générer nos fichiers d’installation APK pour Android et IPA pour iOS, afin de distribuer notre application.
On s’attaque à la navigation entre plusieurs écrans sur notre prochain chapitre.

 

android ios react native expo Cours web Mobile – React Native

Chap 1 : Environnement, prérequis & Hello world !

Résultat du cours

Objectif

  • Configurer l’environnement de développement
  • Générer le squelette basique d’une application
  • Tester son application sur son smartphone

 

Code source du chapitre disponible sur Github.
 

 

ReactNativeCLI, ExpoCLI…

Nous avons des outils dans le développment web, permettant de développer rapidement un squelette de base pour une application :

  • CLI pour Angular
  • CRA pour React
  • CLI pour React Native

 

Mais pour créer mon premier projet pour découvrir ces technos mobile, je pars non pas sur ReactNative CLI, mais sur ExpoCLI. C’est comme Rails mais pour ReactNative, ou encore Phonegap pour Cordova. Il étends les fonctionnalité de ReactNativeCLI.

Qu’apporte t-il de plus par rapport à React Native CLI et quand l’utiliser ?

Avantage :

  • Pas besoin d’Android Studio ni de Xcode
  • Configuration bien plus simple & rapide ( hello world en moins de une minute )
  • Hot reload, sur smartphone physique et non par simulateur. Oui, via l’appli Expo, vous pouvez tester votre app sur votre smartphone iOS ou Android physique, et ce instantanément. En react native vanilla, vous avez droit au simulateur Android sur Windows, et simulateur iOS sous macOS exclusivement.

Inconvénient :

  • Poids de l’apk/ipa, du à l’ajout de librairie annexes (~50mo le hello world, ça fait mal…)
  • Accès aux modules natifs impossible. Vous ne pouvez ajouter de lib natif via Xcode ou Android studio, car tout est packagé via le sdk Expo. Certaines fonctionnalité sont impossible d’être utilisé, comme les achats in-app ou le bluetooth.

 

En résumé, pour débuter le dév mobile ou pour de simples application, vous devriez commencer par Expo. Pour des utilisateurs expérimentés ou souhaitant des fonctionnalités spécifiques à chaque plateforme, partez sur du ReactNative vanilla.

 

Prérequis

Il vous faudra de base :

  • NodeJS

Installez ensuite la CLI de Expo via une console :

npm install -g expo-cli

Pensez à avoir Python dans vos variables d’environnements, au risque d’avoir une erreur d’installation.

 

Initialisation du squelette

On initialise une nouvelle application via la commande :

expo init "Nom_de_votre_app"

 

Vous aurez l’architecture suivante :

  • assets/ : dossier contenant vos images
  • app.json : fichier de configuration du projet
  • app.tsx : fichier d’entrée de votre application
  • package-json : contient l’ensemble des dépendances et scripts du projet
  • tsconfig.json : fichier de configuration de typescript
  • babel.config.js : fichier de configuration pour la gen du bundle ( une sorte de webpack )

 

Lancement du serveur de dév

Simple :

npm start

Un nouvel onglet dans votre navigateur va s’ouvrir, vous proposant divers options :

 

Pour faire fonctionner le simulateur Android ou iOS, vous allez devoir installer les biblio natives. Mais on peut éviter cela en utilisant notre propre smartphone. On va devoir connecter notre smartphone au même réseau wifi que l’ordinateur sur lequel on développe.

Installez l’application EXPO, disponible sur l’iOS Store et GooglePlay store, selon votre type de device. Une fois l’application lancé sur votre smartphone, vous allez pouvoir scanner le QR code affiché sur la console, comme montré sur la capture d’écran précédent. Cela va permettre de transférer le bundle directement sur le smartphone.

Vous allez pouvoir ainsi voir vos modification en temps réel sur votre téléphone, de l’application que vous codez, à chaque sauvegarde.

 

Icone & Splash screen

Vous pouvez changer l’icone de votre application via le fichier « app.json ».

De même pour le splash screen, qui correspond a l’image qui sera affiché le temps que votre application soit chargé par votre smartphone.

react native chap1 splash screen

 

Conclusion

Nous venons de voir comment réaliser un « HelloWorld » en quelques minutes, et ce directement sur notre smartphone.

On discutera dans le prochain chapitre sur comment générer les fichiers APK et IPA, permettant d’installer et de distribuer notre application.
 

Cours pratiques - Data visualization

Intégration de Plotly.js dans Angular 9

Exemple d’un graphique, venant de mon projet Covid19-Vizualisation

 
Lorsque j’ai voulu me lancer dans la data visualisation intégrée à un site web, j’ai directement voulu utiliser la librairie la plus célèbre en la matière, à savoir D3.js. Mais j’ai trouvé une alternative qui m’a interpellé car basé à la fois sur D3.js ainsi que Stack.gl, permettant de réaliser des graphiques plus interactifs, à première vue.

Celle-ci est disponible à la fois en Python, R, et enfin Javascript, celle qui nous intéresse dans notre article. Et c’est pour cette raison que je l’écris, car celui-ci n’est pas vraiment disponible en Typescript et bien intégré à l’écosystème d’Angular, qui a des notions de modules, de composants, etc.

Comparatif de popularité entre nos deux librairies

 

Objectifs

  • Intégration de Plotly.js
  • Initialisation d’un graph
  • Ajout de données
  • Customisation du type de graph
  • Customisation de son UI

 

Source du projet

Lien vers le dépôt Github contenant les sources

Lien vers une utilisation possible pour réaliser de la Data vizualisation pour suivre l’évolution de la pandémie du Covid19

 

On utilisera des données du Covid19 pour alimenter en data nos graphiques. C’est parti !

 

Quelques infos sur Plotly.js

Pour créer un graphique, on va avoir besoin de trois choses principalement qui se découpe de la façon suivante :

Data

Un objet data qui va contenir l’ensemble des points (ordonnées Y, et abscisse X) que l’on souhaite afficher sur notre graphique.

On le défini dans notre composant en Typescript.

Layout

Un objet layout qui définit les caractéristiques générales au niveau de l’UI de notre graphique, comme le titre, la taille de notre graphique, etc. Si l’on souhaite modifier l’allure d’une courbe en particulier, cela se fera dans l’objet data cependant.

On le défini dans notre composant en Typescript.

Config

C’est l’objet final crée, qui englobe notre objet Data ainsi que notre objet Layout.

On le défini dans notre composant en Typescript, et on ira le binder avec notre fichier de vue en HTML.

 

Intégration de Plotly.js

Je commence par initialiser un nouveau projet Angular pour illustrer notre exemple. Je vous renvoie sur un précédent article, expliquant comment initialiser une application Angular.

On installe via npm les modules nécessaires :

  • npm install angular-plotly.js plotly.js

On ajoute le module Plotly à notre module globall App :

Dans votre fichier de configuration tsconfig.json, passez ‘target’ en ‘es5’, si vous avez une erreur dans votre console comme quoi Plotly n’est pas défini dans votre document.

 

Création d’un graphique avec une courbe

Partie vue

On ajout un composant ‘plotly-plot’. Celui-ci est composé de plusieurs directives et attributs :

  • fxFlex & Style : directive FlexLayout de Angular, permettant à notre composant de prendre toute la hauteur et largeur du parent disponible
  • useResizeHandler : directive permettant de resize automatiquement le graphique selon la taille de la fenêtre
  • data: object contenant l’ensemble des données du graphique
  • config: object contenant la configuration général de notre graphique
  • layout: object contenant la configuration graphique de notre graphique

 

Partie composant

On déclare nos attributs généraux :

 

J’initialise mes précédents attributs dans le constructeur du composant :

 

Par la suite, je vais charger mon fichier de données. J’utilise un fichier CSV qui va être lu en local via le httpClient :

 

Enfin, ma fonction permettant de parser mon fichier CSV de string :

Le plus important sont les lignes suivantes :

  • 4-5 : création de tableau temporaire, contenant nos données
  • 14-15: on remplit nos tableau déclarés précédemment des données du fichier CSV en cours de parsage
  • 23-24: ajout de nos nouvelles données

 

Voici le résultat de ce que l’on obtient selon le type de graphique que l’on choisit dans notre objet de data :

 

Vous avez une multitude de type de graphique selon ce que vous voulez donner comme aspect à vos données, je vous laisse lire la doc pour en savoir plus.

 

 

Création d’un graphique avec une multitude de courbe

On va reprendre l’exemple précédent, et y ajouter une nouvelle courbe concernant les cas soignés. Je vais enlever quelques données en début de pandémie, étant donné que l’on a eu des cas à partir du 1er Mars à peu près. Cela permettra une meilleure visibilité pour mon tutoriel.

 

On commence par ajouter une nouvelle courbe en ajoutant une donnée dans notre tableau de données. On fait cela comme précédemment, dans le constructeur du composant :

Vous pouvez apercevoir quelques changements comparé à la première partie de ce tutoriel :

  • marker : permet d’affecter une couleur à notre courbe
  • name : nom de la courbe dans la légende
  • legendgroup : permet de grouper plusieurs courbes dans un même groupe, et de pouvoir les cacher en cliquant dessus dans la légende pour toute les faire disparaître

 

La dernière étape va être de modifier notre fonction de parsing de notre fichier CSV qui contient nos données, afin de récupérer des informations pour une seconde courbes, qui sera elle concernant les cas soignés :

  • Lignes 4 : L’axe X des abscisses ne change pas, puisque on veut garder nos dates.
  • Lignes 6 et 18 : On va créer un nouveau tableau contenant des nombres, et le remplir de la même façon que précédemment, mais avec un indice différent et donc une donnée différente.
  • Lignes 29-30 : correspond à notre second objet de données créer précédemment. On fait attention de lui affecter en abscisses nos données DATE, et en ordonnés notre tableau contenant le nombre de cas soignés.

 

Voici le résultat de ce que l’on obtient selon le type de graphique que l’on choisit dans notre objet de data :

 

 

Quelques exemples de customisation de l’UI

Je vous présente quelques attributs plutôt chouettes pour changer rapidement le sous type de nos graphiques que je vous ai présenté précédemment, à savoir Scatter et Bar

Vous avez moyen de vraiment poussé beaucoup de chose dans l’UI du graphique, regardez la documentation si vous voulez des envies bien précises.

Sous-type de BAR

L’attribut ‘barmod’ se définit dans l’objet LAYOUT de notre graphique ( attribut ‘layout’ dans nos exemples précédents )

 

Espacement de BAR

Vous pouvez gérer l’espacement entre les bars pour optimiser la lisibilité de votre graphique. Vous avez deux arguments pour cela :

  • bargap : espacement entre les bars d’un même groupe
  • bargroupgap : espacement entre les bars de groupes différents

Ces deux arguments se définissent dans l’objet LAYOUT.

 

Sous-type de SCATTER

L’attribut ‘mode’ se définit dans l’objet DATA de notre graphique ( attribut ‘allData’ dans nos exemples précédents )

 

Conclusion

Vous avez donc accès pleinement à la librairie Plotly.js dans votre application Angular.

Rien de bien complexe sur son intégration donc, juste un zeste déroutant d’utiliser du Javascript dans du Typescript, on mélange du typage fort avec des objets que l’on remplit d’attributs à la volé.

Vous pouvez ajouter des events de clic, de listener, pour rendre tout cela un peu plus dynamique comme par exemple divers chargements de données pour combiner plusieurs sources, modifier en temps réel l’allure et l’UI des graphiques, etc.

 

electron jest spectron e2e unitaire test Cours logiciel - Electron

Chap 8 : Tests unitaires & end-2-end ( Spectron…

C’est lassant, ça prend du temps, et c’est bien souvent idiot au premier abord. Je vous présente donc….. les TESTS ! 😒 On les évites bien trop souvent, mais il faut le dire moi le premier, que l’on a tous connus des projets auquel à force de rajouts de fonctionnalités, que certaines unes d’entres elles, ont sans le vouloir casser d’autres fonctionnalités. En effet, quand on est sur une branche et que l’on focus cette nouvelle feature, on test celle-ci exclusivement dans l’environnement de développement. Et il se peut que l’on casse d’autres chose à vouloir bouger, modifier et optimiser notre code. Et on s’en rend bien souvent compte trop tard lors d’éventuelle realease en production, ce qui peut engendrer d’importantes conséquences. Ou dans le meilleur des cas comme moi, passer pour un con lors de mes démos 😅

 

Objectif

  • Installer & adapter les environnements Jest et Spectron à Electron
  • Réaliser des tests end-2-end
  • Réaliser des tests unitaires

 

Spectron & Jest : pourquoi et comment

Lors de la création d’un projet Angular via CLI, vous aurez d’avantage de chance de connaître les noms de Karma, Jasmine, ou encore Protractor, qui sont proposé par défaut.

 

  • Pourquoi migrer de framework si ceux de base sont proposé par Angular ? 🤔

 

Et bien pour deux raisons :

  1. Jest est vraisemblablement plus rapide que ses concurrents pour effectuer ses tests, car ils peuvent s’exécuter en parallèle. Vous gagnez donc au change, au fil du temps que votre application se développe.
  2. La seconde est que même si on créer à première vu un site web, il a néanmoins pour but d’être utilisé sous forme d’application bureautique via Electron. Les framework de test cité plus haut sont formidable pour tester des sites web. Cependant, comme on fait appel à des fonctions de l’API de Electron, on ne peut ouvrir notre application Electron convenablement sur notre navigateur favori. Ceux-ci ne vont donc être utile que vous du test unitaire, mais on peut dors et déjà oublier les tests e2e. C’est pour cela que Spectron est idéal, puisque développé pour tester des applications conçu sous Electron.
  3. Donne la couverture de code couvert par les tests
  4. Pas besoin d’un navigateur web pour exécuter les tests, tout se fait depuis la console
  5. Réalisation de ‘snapshot’, afin d’assurer que l’on ait pas de régression d’un point de vue UI

 

Jest

C’est le moteur de test développé par Facebook. Pratique, car tourne sur Angular, React, Vue.

 

Spectron
Spectron wrapper de WebDriverIO et Selenium

C’est un wrapper qui embarque à la fois Selenium, et WebDriverIO.

  • Selenium est un framework de test, qui permet de réaliser des opérations sur le navigateur web.
  • WebDriverIO quant à lui, est un autre framework de test qui reprend l’API de Selenium de façon customisé, écrit en javascript et exploitable par NodeJS. Il va ainsi ajouter des fonctionnalités de binding. On va pouvoir réaliser des opérations de click de souris sur des éléments, récupérer des champs de valeur, naviguer dans notre application, etc. Concrètement, on va pouvoir reproduire une utilisation du logiciel par un vrai utilisateur, mais en ligne de code.
  • Spectron, enfin, va ajouter des fonctionnalités pour avoir accès à l’ensemble de l’API de Electron

 

Optionnel : bibliothèque d’assertions

Lorsque on effectue des tests, on compare un état souhaité, avec l’état réellement obtenue lors de l’utilisation de l’application. J’utilise la librairie de base de NodeJS, à savoir assert. Simple et facile d’utilisation. Mais il est vrai que certains préférerons d’utiliser des styles d’écriture BDD ou TDD. Chai est une librairie que je recommande, qui permet de faire cela, tout en poussant les fonctionnalités de comparaison pour avoir des tests encore plus poussé.

Exemple de style que vous pouvez rencontrez, pour faire une comparaison de base :

  • Should : foo.should.equal(‘bar’);
  • Expect : expect(foo).to.equal(‘bar’);
  • Assert : assert.equal(foo, ‘bar’);

 

Spectron & Jest : utilisation

Installation

On commence par installer les modules nécessaire, en dépendance de développement via le gestionnaire de packets NPM :

Jest : npm install –save-dev jest

Auto complétion Jest : npm install –save-dev @types/jest

Spectron : npm install –save-dev spectron

 

/!\ Attention /!\

Veillez à bien respecter les versions entre Electron et Spectron, ou vous risquez d’avoir des soucis de compatibilité :

Electron Version Spectron Version
~1.0.0 ~3.0.0
~1.1.0 ~3.1.0
~1.2.0 ~3.2.0
~1.3.0 ~3.3.0
~1.4.0 ~3.4.0
~1.5.0 ~3.5.0
~1.6.0 ~3.6.0
~1.7.0 ~3.7.0
~1.8.0 ~3.8.0
^2.0.0 ^4.0.0
^3.0.0 ^5.0.0
^4.0.0 ^6.0.0
^5.0.0 ^7.0.0
^6.0.0 ^8.0.0
^7.0.0 ^9.0.0
^8.0.0 ^10.0.0

 

Configuration

On va créer un fichier de configuration pour jest, jest.config.json, à la racine de notre projet :

  • testMatch : définit une regexp pour matcher le nom des fichiers de tests. Ici, on garde les fichiers dans le dossier /e2e/,  et qui contient le mot .e2e. ou .unit. et qui est un fichier TS ou JS

 

Ensuite, on va ajouter un nouveau script pour automatiser le lancement de nos tests, dans notre fichier package.json :

  • config : pour renseigner la configuration crée précédent
  • runInBand : lancer les tests de façon séquentiel
  • detectOpenHandles : autorise Jest à fermer une session d’un test automatiquement si celui-ci ne se termine pas correctement, afin de continuer les tests

 

Squelette de base d’un test

Voici le template de base pour réaliser un test :

  • describe : c’est le mot clé pour définir un groupe de test
  • beforeEach : permet de retourner une application lancé a chaque début de test
  • afterEach : permet de fermer notre application une fois un test exécuté
  • it : mot clé pour définir un test

Vous pouvez observer la mise en place d’un timeout par Jest, mais aussi dans la définition de notre application. Cela permet de laisser un peu de temps à notre application pour s’ouvrir, avant de pouvoir l’utiliser.

L’ensemble des interactions possible via WebDriverIO sont disponible sur leur page de leur API.

 

Le code est exécuté de façon asynchrone. Vous allez donc devoir les rédiger soit en utilisant async/await, ou en utilisant des promesses. Chacun ses préférences, même si je trouve le code avec des async/await bien plus lisible et compréhensible.

 

Exemple de test

Je vous donne quelques exemple de tests simples, pour vous donnez des idées. Vous verrez les tests les plus simple à savoir cliquer sur des bouttons, récupérer des valeurs de champs de texte, accéder à l’API de Electron…

 

Vérifier que les outils de développement de Chronium ne sont pas ouvert 

 

Lire le contenu d’un champ texte

 

Vérifier la navigation entre module et composant

 

Tester l’application en plein écran

 

 

Conclusion

Spectron est la librairie officiel pour tester des applications sous Electron.

formation electron transpilation tsc Cours logiciel - Electron

Chap 7 : Backend en Typescript ( transpilation via…

Nous avons vu précédemment comment build et package l’ensemble de notre application en un .exe ou un installateur, si on souhaite le distribuer dans le chapitre précédent.

Je pensais avoir déjà fait un rapide tour d’Electron en 6 chapitres, mais à force de l’utiliser je pense pouvoir ajouter quelques chapitres supplémentaires qui pourrait bien vous servir et faciliter le développement autour de ce génial framework.

 

 

Objectif

  • Diviser les fonctionnalités de notre unique fichier du backend (main.js) en une multitude de fichiers
  • Permettre d’écrire le backend en Typescript et plus Javascript via un transpileur (TSC)
  • Pouvoir transpiler en instantané ( hot reload )

Le code source concernant ce chapitre est disponible sur mon Github.

 

 

Passage du Javascript vers le Typescript

Pour le moment, nous avons l’ensemble de notre application du frontend écrit via Angular en Typescript, mais le backend en Javascript. Il faut dire que le TS apporte beaucoup au JS traditionnel, et c’est pour cela que j’ai décider de migrer le backend. Il faut savoir que seul le pure javascript est compréhensible de nos navigateurs.

 

  • Comment Angular peut-il alors faire du frontend alors que l’on écrit notre application en TS ? 🤔🤔

 

De façon invisible, nous avons Webpack, planqué dans Angular, qui nous créer notre bundle en effectuant une multitude de transformation de nos fichiers, donc une que l’on va voir maintenant, est qui est la phase de transpilation. Celui-ci va transpiler l’ensemble de nos fichiers TS. Un mot bien complexe qui n’est rien d’autre que la conversion des fichiers TS en JS.

 

Script NPM pour la transpilation du typescript

Je suis parti sur TSC, qui est le transpiler de base de Typescript, car il est très simple d’utilisation, pas besoin de s’embêter avec un tas de paramétrage pour transpiler deux pauvres fichiers TS. Si vous souhaitez vous lancer dans des utilisations plus poussés, renseignez vous auprès de Webpack ou encore Babel.

 

On ajoute premièrement à notre package-json un nouveau script pour nous permettre d’appeler TSC :

  • backend-serve : nom du script
  • –project : argument pour fournir un fichier json de description pour le transpiler
  • –watch : argument pour compiler à la volé, dès qu’une sauvegarde de code est détecté

 

Si vous souhaitez transpiler seulement une fois sans avoir besoin du rechargement à la demande, vous pouvez supprimer l’argument ‘–watch’.

 

Une fois le script ajouté, on va créer un nouveau fichier comme vous avez pu le lire précédemment, tsconfig.backend.json, qui va nous permettre de décrire comment nous souhaitons transpiler nos fichiers TS.

Les arguments les plus importants sont :

  • include : on liste ici l’ensemble des fichiers TS que l’on souhaite transpiler
  • baseUrl : décrit la base du projet. On s’en servira plus tard lorsque je parlerais d’import de module en absolue ou relatif.

 

Ré-écrire son Main.js en typescript

Le but va être de ré-écrire son fichier d’entrée de notre application Electron, Main.js, en une version typescripté. Ouais je sais que ce mot existe pas, et alors c’est mon blog !😋

La ligne 5 représente un import de module pour les fichiers JS, la ligne 6 la méthode pour les fichiers TS

On va copier notre fichier Main.js et en faire un nouveau Main.ts. Vous risquez d’avoir quelques erreurs de lancé par votre linter, rien de bien complexe à modifier, vous devriez vous en sortir sans grand soucis. Un exemple dont vous pouvez avoir est la façon dont vous devez importer vos modules.

 

 

Je vais néanmoins quand même vous accompagner pour vos premières classes, car vous risquez d’avoir un petit soucis 😜

 

 

Architecture du backend

Jusqu’à présent nous n’avions qu’un seul fichier pour le backend, pour la gestion du cycle de vie de notre application. Au fur et à mesure des fonctionnalités que vous allez ajouter au backend, il se peut que vous souhaitiez éclater ce fichier ‘main.js’ en une multitude d’autres afin d’avoir une plus fine granularité, et ainsi d’améliorer l’extensibilité du code dans le futur. Je vous propose de suivre l’architecture suivante :

 

On va ajouter les deux classes suivantes :

  • StorageManager : on va lui déléguer l’ensemble des fonctionnalités de Main.js qui touche l’ensemble des serialization des données du module electron-store
  • CommunicationManager : on va lui déléguer l’ensemble des fonctionnalités de Main.js qui touche à l’échange d’informations entre le render et le main process, soit l’ensemble des fonctions du module IPC.

 

Erreur du loader/resolveFilename

Vous avez enfin une belle architecture, écrite en TS, et vous avez TSC de configuré. Aucune erreur sur l’ensemble de vos consoles, super, vous pouvez lancer Electron… et BIM ! Une belle erreur devrait apparaître, comme quoi vos nouveaux composants fraîchement crées ne sont pas trouvable 😒. Tsc étant un transpiler simple, il ne fait pas la liaison entre les composants lorsque on utile des imports absolue. Cependant si vous utilisez des importation de module avec des liens relatifs, vous n’aurez pas de soucis. Cependant, l’écriture de ces imports rend leur lecture complexe, en voici un exemple :

import * as test from ‘../../../../../../monModule’;

 

  • Mais pourquoi la console de TSC ne m’a pas indiqué d’erreur lors de la transpilation, mais seulement au moment de lancer Electron ? Car nous l’avons paramétré dans le fichier tsconfig.backend.json, avec l’argument ‘baseURL’ souvenez vous.

 

Si j’ai fais ce tutoriel avec TSC, c’est qu’il existe néanmoins des solutions, même si je vous avoue m’être bien cassé la tête sur ce problème. Pour résoudre ce soucis de chemin dans les require, vous avez deux petits modules à la rescousse disponible sur NPM.

 

Méthode 1 – La plus simple & basique

Son principe est simple, il va ajouter le répertoire parent de plus haut niveau dans le module de recherche de chemin de Node.

 

Il suffit d’installer le module suivant :

npm install app-module-path –save

C’est la méthode la plus simple, car il suffit d’ajouter une seule ligne de code, au début de notre fichier main.ts :

Pratique, car fonctionne lors du build, mais aussi en mode hot-reload durant le développement.

 

Cependant, si vous souhaitez seulement tester un fichier en particulier, une classe par example, et donc ne pas lancer votre application entière via le main.ts (faire simple un => node maclasse.js), cela ne fonctionnera pas car ayant ajouté le code précédent dans le main.ts, celui-ci ne sera pas lu. Pour cela vous êtes soit obligé de toujours lancer le main.ts depuis node pour que l’ensemble des imports soient modifiés, soit ajouter ce code dans l’ensemble des classes, ce qui peut vite devenir lassant. C’est pour cette raison là que je vous conseille la méthode 2.

 

Méthode 2 (recommandé) – Un poil plus complexe, mais plus flexible

Un second module vient à notre rescousse mais se comporte tout autrement. En effet, il va aller modifier les imports absolue de chaque fichier pour les remplacer par des liens absolue lors du build, dans les fichiers transpilé .js. Terriblement efficace, et pas bien plus complexe en ne nécessitant qu’une petite étape supplémentaire de configuration.

On installe ce module via:

  • npm install ttypescript --save
  • npm install @zerollup/ts-transform-paths --save

Héhé, je vous en fait installer un second en cachette car nous allons avoir besoin d’un wrapper, ttypescript, qui va nous permettre d’utiliser des plugins de transformation qui sont supporté dans notre fichier de configuration des options de compilation, disponible dans le fichier tsconfig.json.

 

Premièrement, on va modifier notre script NPM du fichier package.json de tout à l’heure pour qu’il utilise ttypescript que l’on vient d’installer :

 

On va ensuite modifier notre fichier de configuration qui permet de transpiler le backend, tsconfig.backend.json, afin de lui ajouter notre transformateur dans l’option ‘plugin’ pour qu’il puisse ré-écrire les imports :

Et on lui dit dans l’argument ‘paths’ de récupérer tout les fichiers à la base du projet et de les importer tel quel.

 

C’est finit, vous n’avez plus qu’a builder le backend depuis la console, avec notre script npm via la commande :

npm run backend-serve

Pour tester si tout fonctionne lancer le serveur de développement Angular avec:

npm run angular-serve

Ainsi que electron via :

npm run electron-serve

 

Mise à jour de la configuration du build

Afin de pouvoir continuer à builder, packager et distribuer votre application avec le module electron-builder, n’oubliez pas de modifier votre configuration de build disponible dans le fichier electron-builder.json ( ou dans votre package.json si vous n’avez pas dissocié les fichiers de configuration ). En effet, venant de modifier le backend en une multitude de nouveau fichiers TS et JS, nous devons mettre à jour notre configuration afin que celle-ci les prennes en compte dans le packaging de l’application. Pour cela, on va ajouter un nouvel item dans l’argument ‘files’, afin d’ajouter nos fichiers javascript précédemment transpilé :

 

Conclusion

On vient de voir la façon la plus simple pour pouvoir transpiler son backend Electron via TSC et un transformateur, pour résoudre les liens des imports absolue en relatif. Cela va nous permettre d’utiliser le typage et ainsi d’avoir un code source plus rigoureux grâce à Typescript.

 

Cours logiciel - Electron

Chap 6 : Build, package et distribution (installateur) de…

Nous avons vu au chapitre précédent comment améliorer l’UI de notre application avec un système permettant à l’utilisateur de choisir son thème. Cela se fait beaucoup actuellement sur les applications pour reposer notamment les yeux lors d’une utilisation nocturne. Nous avons aussi vu comment sérialiser simplement et rapidement des données utilisateurs concernant les préférences et paramètres de l’application via de simples fichiers JSON.

Le code source concernant ce chapitre est disponible sur mon Github.

 

Principe global

Dans ce sixième et dernier chapitre de cette série consacré à l’utilisation de Electron, nous allons voir comment packager notre application afin de la distribuer. Pour cela nous allons utiliser le très bon module Electron-builder pour créer nos installateurs. On va installer ce module en tant que dépendances de dév :

  • npm i electron-builder -g

 

Nous allons devoir réaliser deux principales étapes afin de créer notre installateur :

  1. Builder notre application Angular en mode production,
  2. Packager le précédent build via Electron-builder.

 

Génération du build Angular en mode prod

Cette première étape va consister à créer un bundle de notre application. On va demander à Angular de builder notre application en mode production afin de compiler l’ensemble de nos composants, contrôleurs et pages web avec nos modules NPM, afin de passer d’un dossier de quelques centaines de Mo à un build ne pesant que quelques Mo.

Nous allons devoir effectuer quelques modifications de code, car actuellement on ne fait que build notre application dans un environnement de développement via notre serveur local.

 

Chargement de la page d’accueil

Pour le moment on demandait à Electron de charger à l’initialisation de la fenêtre, le rendu du serveur local de Angular via :

win.loadURL('https://localhost:4200/')

On va ajouter du code permettant de demander le chargement de index.html de notre build dorénavant :

On va demander de charger un fichier et non plus une URL, en indiquant via le paramètre protocol. Le chemin correspond au fichier index.html dispo dans notre build, situé dans le dossier ‘dist’ de Angular. Le paramètre slashes est extrêmement important pour Angular, afin de permettre le routage des diverses pages au sein de notre application.

 

Activer le Hash (#)

Etant donnée que l’on crée une SPA ( Single Page Application ), on peut observer des # dans notre URL, mais pas pour tout le monde, puisque Angular le cache dans les dernière version, et cela pose problème.

En effet avec le serveur de dév, tout fonctionne bien. Mais une fois passé en mode production, on arrive plus à afficher nos pages web correctement, car l’URL est faussé sans notre #. Pour cela, on va devoir le spécifier dans notre module principal de routing, d’utiliser le hash :

 

Base des liens

On va aller modifier la base de l’ensemble des liens de notre application, disponible dans notre index.html afin qu’il corresponde avec Electron :

<base href="./">

 

Cible de build

Dans le fichier de configuration de build de Angular, tsconfig.json, on va modifier la ligne suivante :

  • « target »: « es2015 »

par :

  • « target »: « es5 »

 

Génération du build

Dernière étape, on va générer le build Angular via :

  • ng build –prod

Le build est dispo sous /dist.

 

Pensez à tester ce build de production directement avec Electron avant de passer à l’étape suivante, via la commande :

  • electron .

Sans utiliser notre arguments –devTools, on demande à electron de tester notre build précédemment crée et non le serveur de développement de Angular.

 

Tout fonctionne pour moi, on peut passer à l’étape finale 😎

 

/!\ Attention à bien vérifier les liens vers vos assets, qu’ils soient bien relatif et non absolue, sinon vous risquez d’avoir des soucis et ne seront pas trouvé dans votre app Electron !

 

Package du build via Electron-builder

Vous avez de disponible quelques modules pour vous permettre de vous faciliter la vie pour créer votre installateur. En voici les principaux :

Comparatif des modules de build/package les plus populaires

Je vous propose de partir sur le plus populaire du moment de Github, à savoir Electron-builder. Mais vous pouvez partir sur celui qui vous fait plaisir, je n’ai pas essayé les autres mais je présume qu’ils doivent chacun faire le boulot !

 

Du coup avec le notre de module, c’est plutôt simple. On a juste à définir de nouveaux comportements dans notre fichier main.js. Je vous montre la spécification minimal, la plus simple pour générer un installateur. De nombreuses autres options sont disponible sur le site de Electron-builder, que cela soit pour faire un build Window, Linux ou macOS.

appId : nom de l’application

compression : définit le niveau de compression des données de notre application dans l’installateur

win : on définit ici les options pour un build pour window, à savoir la cible ainsi que le fichier d’icone pour notre application

electronDowload : permet de mettre en cache les utils et dépendances nécessaire à Electron builder afin de compiler notre installateur

directories : on définit le dossier d’output pour notre installateur

nsis : c’est la cible concernant un build pour window, on définit les options ici de l’installateur. On lui spécifie que on veut laisser le choix à l’utilisateur pour installer sur une session ou en global, la possibilité de choisir son dossier d’installation ainsi que de supprimer ou non les données de l’application en cache une fois celle-ci de supprimé

files : c’est ici que l’on spécifie à Electron builder les fichiers nécessaires au bon fonctionnement de notre application. On lui donne notre point d’entrée de notre app qui est main.js, ainsi que notre package.json ou l’ensemble du fonctionnement y est spécifié, et enfin le build de production généré par Angular précédemment

 

Pour générer l’installateur, ouvrez votre console dans le dossier du projet et tapez :

  • electron-builder

Il va télécharger les dépendances et utilitaires nécessaire pour créer l’installateur. Vous pouvez lui spécifier des arguments pour définir quelle plateforme et quelle architecture cible vous souhaitez pour votre/vos installateurs.

Dans votre dossier de sortie de Electron builder, sous /distElectron, vous aurez à la fois un dossier avec l’ensemble de votre application buildé et packagé prêt à fonctionner ( on peut appeler ça une installation dite portable, d’un simple copié/collé vous partagez votre app) ainsi que d’un installateur au format .exe traditionnel.

 

Astuce : builder en mode offline

Electron-builder va descendre certaines extension pour réaliser le build. Si vous souhaitez réaliser des builds en mode offline, sur un pc n’étant pas connecté à internet, vous pouvez mettre une variable d’environnement pour forcer le cache de electron builder dans le dossier spécifique de votre choix :

  • set ELECTRON_BUILDER_CACHE= »votre_dossier »

 

Vous aurez ainsi dans ce dossier les éléments suivants :

ELECTRON_BUILDER_CACHE :

  • votre_dossier
    • nsis
      • nsis-x.x.x.x
      • nsis-ressources-x.x.x
    • winCodeSign
      • winCodeSign-x.x.x

 

Vous aurez plus qu’a récupérer ce dossier, et de les déposer via usb sur votre nouvel ordinateur qui ne dispose pas d’un accès internet. N’oubliez pas de re-set la variable d’environnement sur ce dernier pc pour lui indiquer le bon chemin pour accéder à ce même dossier.

 

Conclusion

On arrive avec de sixième chapitre à la fin de la série consacré à comment débuter sur Electron. Vous êtes désormais capable de :

  • Initialiser un nouveau projet, développer avec un serveur de dév en local avec hot reload du frontend & backend,
  • Créer votre première fenêtre avec persistance des données utilisateurs,
  • Gérer la communication entre render & main process, gérer la communication entre composant de Angular,
  • Builder un projet Angular, packager votre application Electron.