React Native et Typescript sur windows, comment bien démarrer ?

Cet article a pour but de présenter dans les grandes lignes les concepts de React Native et d’en montrer la mise en place dans un projet avec Typescript, développé et exécuté depuis une machine Windows.

Introduction à React Native

React Native est un framework de développement Cross Platform développé par (et pour à l’origine) les équipes de Facebook. Il permet, via le langage JavaScript principalement, de créer une application mobile pouvant s’exécuter sur les plateformes iOS et Android. Windows est aussi supporté depuis peu, mais ne fait pas partie des plateformes maintenues directement par les équipes de Facebook. Dans cette famille de framework/environnement de développement mobile, on trouve aussi Xamarin et Cordova. Si cela peut aider à mieux le comprendre, React Native est beaucoup plus proche de Xamarin dans son fonctionnement que de Cordova (malgré l’usage du javascript en commun).

Fonctionnement interne

React Native propose un rendu UI natif, c’est-à-dire qu’il repose directement sur les composants et APIs native de la plateforme d’exécution cible. Pourtant le code produit par le développeur est en JavaScript, alors que les langages natifs des plateformes sont le Java ou l’Objective-C/Swift. On pourrait croire que le code JavaScript est « transformé » en code Natif, mais ce n’est pas le cas non plus. Simplifié au maximum, une application React Native fonctionne avec 3 briques :

fonctionnement-react-native.png

La brique « JavaScript engine » est un thread sur lequel s’exécute un moteur JavaScript (seulement le moteur, pas de couche de rendu UI) avec le code que le développeur écrit en JavaScript. Le code JavaScript peut alors envoyer des messages à la couche « bridge », ceux-ci sont interprétés de sorte à en déduire l’appel à une API native (une modification visuelle sur le thread UI par exemple). La couche bridge va ensuite sérialiser le retour de l’API natif en un message compréhensible pour la couche JavaScript.

L’équipe de Facebook expose ainsi beaucoup d’API natives via des interfaces JavaScript dans son framework. Généralement, ces interfaces sont de mêmes formes pour Android et iOS, ce qui ne nécessite pas d’apprentissage particulier pour cibler une plateforme précise. La contrepartie est que toutes les APIs natives ne sont pas accessibles, il faut parfois faire appel à un plugin tiers de sorte à en bénéficier. L’auteur d’un tel plugin doit prendre à sa charge le développement de l’interface JavaScript et celui d’adapteurs natifs pour chaque plateforme.

Description d’un projet React Native

Pour créer une application React Native, il ne suffit d’écrire ou de récupérer n’importe quel code JavaScript (celui d’une application Web par exemple). En effet, il est nécessaire de développer une application JavaScript React. React est quant à lui une librairie destinée à faciliter la création d’application Web de type SPA. Une application React est faite de composants et repose sur un DOM virtuel. En effet, un composant React ne gère pas directement son rendu dans le DOM du navigateur, il met à jour un état qui permettra de déduire un instantané du DOM souhaité à un instant précis (via le DOM virtuel donc). Les modifications détectées dans ces instantanés sont ensuite répliquées sur le DOM du navigateur. Dans le cas d’une application React Native, les modifications ne sont pas répliquées sur le DOM du navigateur, mais transmise au « bridge » vu précédemment, de sorte à ce que ce dernier puisse demander la mise à jour équivalente du composant UI natif associé.

Ainsi le développeur peut créer et maintenir une application JavaScript React, avec les connaissances acquises dans le monde du Web par exemple, mais bénéficier d’un rendu visuel natif sans compromis de performance, tout en respectant le look and feel de la plateforme s’il le souhaite.

Démarrer un projet React Native

Dans cette section, nous partirons du principe que l’environnement de développement utilisé se trouve sur Windows 10. Nous verrons comment créer un projet et l’exécuter sur Android.

Prérequis

Pour créer une application React Native, il faut commencer par en récupérer la CLI. Cela se fait au travers d’un package NPM. Il faut donc installer NodeJS, via Chocolatey par exemple. La CLI nécessite aussi python et compiler une application Android requiert le JDK :

choco install nodejs.install 
choco install python2 
choco install jdk8

Pour installer la CLI, exécuter la commande NPM suivante :

npm install -g react-native-cli

Création du projet (Native Code)

Il sera ensuite possible de créer une application React Native de cette façon :

react-native init <appname>

Cette dernière commande peut être un peu longue à exécuter mais le temps consommé peut sensiblement diminuer ensuite si vous disposez de Yarn sur votre machine.

Lancement sur un émulateur Android

Pour tester l’application Android fraichement créée, il faut disposer de AVD Manager sur sa machine afin de démarrer un émulateur. Cet outil est normalement installé avec Android Studio. Une fois lancé, l’outil permet de créer un émulateur en se basant sur une définition préexistante :

creation-emulateur-android-avd.png

Vous pouvez ensuite démarrer le projet en commençant par activer le packager (dans une console dédiée) :

cd <appname>
npm start

Puis dans une autre console, en lançant la compilation et le déploiement :

react-native run-android

Si l’émulateur Android a été démarré avec AVD, le déploiement devrait se faire automatiquement :

emulateur-android-avd.png

Lancement sur un device Android

Comme précédemment, il suffit de brancher le device en USB sur la machine de développement et d’y lancer la commande suivante :

react-native run-android

Attention toutefois, pour cibler correctement le device - virtuel ou physique – désiré, il ne faut en connecter qu’un seul. Il est possible de vérifier les devices connectés à l’aide de la commande suivante :

adb devices

Utiliser les outils de développement React Native

Une fois l’application lancée, il n’est plus vraiment nécessaire de la relancer. React Native embarque en effet un système de rechargement automatique du code (via la packager que l’on a lancé avec la commande « npm start » notamment). En secouant un device physique ou en utilisant la commande adb adaptée, il est possible de faire apparaitre le menu développeur :

adb shell input keyevent 82

Ce menu permet par exemple de recharger le code après modification (sans relancer l’application donc).

Il permet aussi d’activer le mode debug du code JavaScript. Ceci fait, un onglet s’ouvre dans votre navigateur (chrome normalement). En ouvrant les outils de développeur de chrome (ctrl + shift + J ou F12) vous pouvez ensuite débugger le code JavaScript (onglet source > debuggerWorker.js > localhost > index.android.bundle). Il est possible d’y ajouter des points d’arrêts, de consulter la console de log, etc.

Une fonctionnalité très intéressante du menu développeur d’une application React Native consiste à activer le « Live Reload ». Ainsi, dès que le packager détectera une modification dans le code, l’application sera automatiquement rechargée avec ces modifications.

Mieux encore, la fonctionnalité « Hot Reloading » impactera vos modifications de code dans l’application sans même la recharger (vous ne perdez pas votre contexte d’exécution).

Attention toutefois, entre l’activation ou la désactivation de ces fonctionnalités, il est parfois nécessaire de relancer l’application sur son device.

Le menu dispose d’autres outils comme un « inspector », permettant de voir les trames réseaux par exemple, ou bien de parcourir l’arborescence visuelle (comme un DOM explorer). De base cet outil fonctionne directement à l’intérieur de l’application, mais pour plus de confort, l’outil react-devtools doit être lancé sur la machine de développement :

npm install -g react-devtools
react-devtools

Tous ces outils ne sont évidemment pas nécessaires pour développer une application React Native, mais leur intégration naturelle dans le cycle de développement augmente grandement la producitivité du développeur, aucune raison de s’en priver !

Mise en place de TypeScript dans une application React Native

Une application React Native peut être développée à l’aide de TypeScript au lieu de JavaScript. Cela relève évidemment des préférences de chacun, mais ce langage peut apporter beaucoup au développeur sans pour autant le limiter par rapport à du pure JavaScript. Evidemment, le code produit en TypeScript sera ensuite traduit en JavaScript et entièrement compatible avec React Native.

Installation des packages

Pour commencer avec TypeScript, il faut disposer des packages NPM requis pour la compilation du code TypeScript :

npm install --save-dev typescript

Afin d’obtenir une bonne expérience de développement et disposer d’une auto-complétion de qualité et d’une vérification des erreurs à la compilation, des fichiers de définitions TypeScript pour React sont nécessaires :

npm install --save-dev @types/react
npm install --save-dev @types/react-native

Préparation de la compilation TypeScript

La compilation TypeScript requiert un fichier tsconfig.json. Vous pouvez le créer manuellement ou bien utiliser la commande suivante :

tsc --init

Toutefois, si vous n’avez pas installé le package NPM typescript en global, la commande précédente ne fonctionnera pas, vous devrez y faire appel via NPM justement. Le moyen le plus simple consistant à créer une commande dans le package JSON, on peut y ajouter le nœud suivant pour commencer (dans le « scripts » existant :

"tsc:init": "tsc --init"

La commande précédente sera donc appelée à l’aide de celle-ci :

npm run tsc :init

Toutefois, les options de compilation générée par défaut dans le fichier tsconfig.json ne correspondent pas exactement à notre besoin. En effet, le moteur JavaScript utilisé dans une application React Native étant extrêmement récent, il supporte toute sortes de fonctionnalités avancées telles que les modules, les décorateurs ou encore les fonctions fléchées et il convient de ne pas les transformer dans un JavaScript antérieur. Voici le contenu du fichier tsconfig.json final :

{
  "compilerOptions": {
    "target": "es2015",
    "module": "es2015",
    "allowJs": true,
    "jsx": "react",
    "sourceMap": true,
    "outDir": "build",
    "rootDir": "src",
    "strict": true,
    "noImplicitAny": true,
    "allowSyntheticDefaultImports": true,
    "experimentalDecorators": true,
    "preserveConstEnums": true
  },
  "filesGlob": [
    "src/**/*.ts",
    "src/**/*.tsx"
  ],
  "exclude": [
    "index.android.js",
    "index.ios.js",
    "__tests__",
    "build",
    "node_modules"
  ],
  "compileOnSave": false
}

Cette configuration implique dorénavant que les fichiers de code « écris » se trouvent dans le dossier src. Une fois compilé en JavaScript, on en trouvera le résultat dans le fichier build.

Pour compiler, on pourra ajouter la commande tsc au fichier package.json (nœud « scripts ») :

"build": "tsc"

Pour lancer la commande, il faudra alors exécuter, dans une console :

npm run build

Pour bénéficier d’une meilleure expérience, il est aussi possible de compiler à chaque modification de code (ce qui peut être intéressant dans les cas où l’on aurait activé le live ou le hot reloading) :

npm run build -- --watch 

Attention, il y a bien quatre traits d’union sur cette commande avec un espace au milieu.

Premiers fichiers de code TypeScript

On commencera donc par créer un dossier src avec le point d’entrée de l’application (index.tsx). On peut alors s’inspirer des fichiers existants (index.ios.js et index.android.js) sans les supprimer pour autant. Les premières instructions restent inchangées, tant en termes de syntaxe que de contenu. En effet, on se contente de charger quelques éléments des modules react et react-native (avec auto complétion et vérification à la compilation toutefois) :

import React, { Component } from 'react';
import {
    AppRegistry,
    StyleSheet,
    Text,
    View,
    Button
} from 'react-native';

Nous pouvons ensuite ajouter la définition du premier composant de notre application, et définir des interfaces pour les props et le state de celui-ci :

interface AppProps {
}

interface AppState {
}

export default class App extends Component<AppProps, AppState> {
}

La méthode « render » peut rester identique à la précédente :

render() {
    return <View style={styles.container}>
        <Text style={styles.welcome}>
            Welcome to React Native!
        </Text>
        <Text style={styles.instructions}>
            To get started, edit index.android.js
        </Text>
        <Text style={styles.instructions}>
            Double tap R on your keyboard to reload,{'\n'}
            Shake or press menu button for dev menu
        </Text>
    </View>
}

L’objet styles reste aussi inchangé :

const styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#F5FCFF',
    },
    welcome: {
        fontSize: 20,
        textAlign: 'center',
        margin: 10,
    },
    instructions: {
        textAlign: 'center',
        color: '#333333',
        marginBottom: 5,
    },
});

Les fichiers index.android.js et index.ios.js doivent ensuite être réécrits comme suit :

import { AppRegistry } from 'react-native';
import App from './build'

AppRegistry.registerComponent('rntest', () => App)

 

Avec cet article nous avons une façon de démarrer un projet React Native tout en y incluant la possibilité d’écrire du code TypeScript. Nous en avons profité pour faire un rapide tour des outils de développement qui s’offrent à nous, en adressant principalement les développeurs sur machine Windows souhaitant tester tout d’abords leurs applications sur Android.

Cet article fait partie d'une série d'articles sur ReactNative :

  1. Présentation de ReactNative
  2. Configurer son environnement de développement ReactNative sur Windows
  3. Configurer son environnement de développement ReactNative sur MacOSX

Ces billets pourraient aussi vous intéresser

Vous nous direz ?!

Commentaires

comments powered by Disqus