Patrice Ferlet
Patrice Ferlet
Créateur de ce blog.
Publié le juin 14, 2020 Temps de lecture: 10 min

Me suivre sur Mastodon

Vue et React avec Typescript pour s'approcher de Angular

thumbnail for this post

Voici comment j’ai retrouvé un de l’intérêt à React, un vrai plaisirs de coder avec Vue - mais aussi pourquoi je continue à militer pour Angular.

Depuis que ES6 (javascript moderne), développer en JS est devenu encore plus adapté aux projets d’envergure. Aujourd’hui, nos navigateurs sont de véritable socles à applications, un site devient une application à part entière qui est interactive et permet de tourner coté client. Depuis des années, les frameworks se sont succédé pour finalement voir au moins 3 frameworks se dégager:

  • Angular1 qui n’est plus un framework JS comme l’était AngularJS, proposé par Google
  • React2 (ou ReactJS) par Facebook
  • VueJS3 qui est développé par un ancien développeur de Angular

Angular se détâche des deux autres car, il est pensé pour développer une application en Typescript, et ne permet pas (du moins pas facilement) de s’intégrer dans une page existante. La philosophie de Angular est de pousser le développement dans le sens de la qualité et d’exploiter les concepts de développement en Typescript, avec des concepts d’injection de dépendance, décorateurs, et une structure très précise. Il est purement MVC4 ce qui est donc bien plus “logique” à utiliser pour un développeur qui vient d’un autre univers (Java, PHP, Python…)

VueJS propose deux mode de développement. Soit en pure JS pour s’intégrer dans une page, ou alors une écriture en “vue file”, qui est en soit une manière de séparer la vue et le controle mais de rester dans le même fichier. Mais ce que je lui reproche c’est le fait de demander de proposer des propriétés spécifiques pour définir les méthodes. Et d’ailleurs, un composant est un objet à retouner et non une classe.

ReactJS est, tout comme VueJS, une librairie qui permet de créer une application ou de s’intgrérer à une page existante. Cela dit, il a une approche un peu spéciale en utilisant JSX et, par conséquent, mélange le HTML au JS. Ce choix divise beaucoup, et je ne suis pas un fan de cette écriture. Cela-dit, j’ai du mal à l’apprécier tel quel. Il manque de standards, d’homogénéité, et ce mélange de code HTML dans le JS ne m’apporte rien, voir me fait perdre en qualité. Mais il faut l’admettre, ReactJS marche très bien.

Bref, React et VueJS sont d’excellents outils, mais je préfère largement Angular pour sa rigueur et son assurance.

Je me suis surtout rendu compte d’une chose importante, c’est que je pense que ce qui me plait énormément avec Angular, au delà de la structure du projet, c’est Typescript. Beaucoup rejettent ce langage qui est pourtant une amélioration compatible de Javascript (vraiment, en fait vous codez en JS mais avec des extensions de langage) - et que c’est un point majeur pour assurer le fonctionnement d’un projet. Le typechecking, les “generics” (je suis pourtant pas un adorateur de cette écriture), etc… je trouve cela rassurant. Angular utilise ce langage à la perfection, et pour cause, il est nativement prévu pour ce langage. La différence se trouve dans le choix par défaut.

Et donc, ReactJS et VueJS ont choisi JSX et JS comme approche native.

oui… mais…

Mais vous le savez certainement, il est possible d’utiliser TypeScript avec React et VueJS. Autaut vous dire que cela change fortement mon point de vue - l’écriture de composant est tout à coup bien plus adaptée, surtout si vous travaillez en équipe. J’ai donc tenté l’expérience sur quelques projets. Et je me suis fait violence pour démarrer un projet en React + TSX (TypeScript à la JSX) pour vraiment creuser sur le fonctionnement et faire preuve d’honnêteté quant à mon analyse.

Et bha… c’est pas mal du tout ! VueJS et React s’en sortent même très bien, et cela m’a apporté bien plus de plaisirs à coder et surtout bien moins de stress pour gérer les erreurs.

Alors comment ça se passe ?

Vue + TS

Depuis que npx5 est sorti, c’est bien plus simple de démarrer un projet sans trop se prendre la tête. Le client “vue” propose des options qu’il faut regarder. L’idée est de passer par le choix “manuel”:

npx -p @vue/cli vue create my-ts-application

Il faut passer par le menu “Manually select features” et sélectionner (avec la touche espace) les options suivante:

  • Babel
  • Typescript
  • Router (je le recommande)
  • CSS preprocessor (vous choisirez celui qui vous plait)
  • Linter / Formatter (encore une fois c’est conseillé)
  • Unit Testing (optionnel mais on aime faire de la qualité n’est-ce pas ?)

Ensuite, je vous coneseille fortement de laisser les choix par défaut (“Use class-style component syntax”, “Babel along Typescript”…), sauf l’option ESLint que je trouve plus adapté avec “Prettier”.

Donc, le résultat:

? Please pick a preset: Manually select features
? Check the features needed for your project: Babel, TS, Router, CSS Pre-processors, Linter
? Use class-style component syntax? Yes
? Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)? Yes
? Use history mode for router? (Requires proper server setup for index fallback in production) Yes
? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default): Sass/SCSS (with node-sass)
? Pick a linter / formatter config: Prettier
? Pick additional lint features: Lint on save
? Where do you prefer placing config for Babel, ESLint, etc.? In dedicated config files

Alors, ça change quoi ?

Et bien voilà à quoi ressemble une Vue:

import { Component, Prop, Vue } from "vue-property-decorator";

@Component
export default class HelloWorld extends Vue {
  @Prop() private msg!: string;

  onButtonClick() {
    this.msg = "Clicked !"
  }
}

On a enfin une vraie classe exportée, les méthodes, data, etc sont enfin des éléments de la classe et non des propriétés à écrire dans une propriété spécifique. Les décorateurs @Component et @Prop proposent de configurer notre classe de manière claire. Tout change ! Et bon sang que c’est plus pratique pour coder.

@Prop est clairment l’équivalent de @Input de Angular - on retrouve vite ses petits.

Juste un point important - n’oubliez pas que la balise “script” doit avoir l’attribut lang="ts", c’est à dire: <script lang="ts">...

En ce qui concerne la reconnaissance de syntaxe dans VSCode (ou VSCodium si vous préférez une version plus respectueuse de votre vie privée), passez par le plugin “Vutter” va vous donner satisfaction. Il reconnait très bien le code TypeScript.

React + TSX

Je ne suis pas un fan de React (loin de là) - je le trouve peu rigoureux (on peut écrire un composant avec une fonction ou une classe, le routing se fait dans la vue, et la vue se trouve dans le code… bof…). Mais je dois être honnête, il est pratique et simple. Je comprend l’engouement qu’ont les développeurs Web pour cette techno.

Mais il faut que je le reconnaisse aussi, avoir utilisé React avec TypeScript m’a donné bien plus de plaisirs.

Comment on fait ?

npx create-react-app my-ts-react --template typescript

Bon… Déception, l’application générée ne propose pas un composant exemple. Mais en soit c’est assez simple de trouver la manière de faire. Voici un petit exemple:

import React, { Component } from 'react';

export default class Foo extends Component {
    render() {
        return <div>Mon Composant !</div>
    }
}

Vous allez me dire “ok… super… c’est juste plus lourd que d’écrire une classe JS ou une fonction… super ton idée”, mais non !

Tout d’abord, la gestion d’état (statefull) est plus simple et surtout plus claire en utilisant l’écriture génériques. Idem pour les propriétés qui peuvent être des interfaces à part entière:


// Des propriétés du composant
// comprennez par là: attribut de la balise
interface Profile {
    name: string,
    age: number
}

// Une interface pour les états
interface Activated {
    isActive: boolean
}

// on utilise cet état et les propriétés dans notre classe
export default class Foo extends Component<Profile, Activated> {

    state: Activated {
        isActive: false
    }

    activate = () => {
        this.setState({
            isActive: !this.state.isActive
        })
    }

    render() {
        return <div>
            <p>{this.props.name} - {this.props.age} ans - {this.state.isActivate}}</p>
            <p><button onClick={this.activate}>(De)Activate</button></p>
        </div>
    }

}

On a donc enfin du type checking, des classes bien plus claires et faciles à adapter, une logique d’écriture de projet plus adaptée à un environnement plus large. On réduit drastiquement le nombre d’erreurs.

Bon, par contre, la perte de contexte dans la vue est toujours actuelle… donc les “handlers” doivent être déclarés en “arrow fuction” (source d’erreur…)

Bref, j’ai clairement redécouvert React en passant par TypeScript.

Du coup, je quitte Angular ?

Et bien… non. 😁 - du moins, sur les gros projets, je reste sur le fait que Angular est plus adapté. Mais pour des applications plus légère, ou dans le cas où Angular peut faire peur, je pense pouvoir proposer React avec TSX. Quant à Vue, je le propose généralement si Angular est refusé, et j’essai de faire passer l’idée d’utiliser TS. Vous l’avez compris, React est mon 3ieme choix. Mais dites-vous que quelques semaines auparavent je refusais simplement de le proposer. J’ai simplement pris conscience que c’est la structure projet d’une applicaiton React qui me gène (je parle de structure de code, pas de la structure logicielle car, avec de la rigueur, on peut structurer une applicaiton proprement avec n’importe quel techno)

Angular est, de base, prévu pour développer en Typsescript. Il propose l’injection de dépendance et le routage par défaut. Ses templates sont bien séparés du controlleur, et je trouve que la gestion des requêtes HTTP (incluses nativement) est beaucoup plus adaptée que celle de React et VueJS (non native, pas standard).

J’apprécie aussi énormément le langage de template de Angular - celle de Vue me va, alors que je trouve React bien en dessous en terme d’écriture. Par exemple, faire une boucle d’affichage dans React n’est pas générique, il y a plein de façons de faire, et (je sais que cet argument ne vous ira pas) ce n’est pas du tout commun par rapport à Jinja / Twig ou à ce qu’on peut trouver ailleurs. J’attends que React propose une vraie amélioration de ce coté.

De plus, Angular a un ecosystème que j’adore, par exemple ng-bootstrap… Je sais qu’il existe des équivalents chez React et VueJS, mais l’intégration est selon moi bien mieux pensée dans l’univers Angular.

Vue me parait aussi plus simple que React, y compris avec TypeScript. Pas besoin de mettre des arrow functions pour éviter de perdre le contexte avec les handlers, et il ne demande pas l’utilisation de “generics” pour ajouter une propriété de composant. Idem pour la gestion d’état qui est plus lourde chez React. Clairement, Vue utilise Typescript de manière plus optimale que React, mais encore une fois Angular est un cran au dessus à ce niveau.

Je ne rejette pas React. Je n’ai juste pas la même philosophie d’écriture de projet que celle proposée par ce framework. Cela étant dit, si je dois démarrer un projet React à l’avenir, je vais militer pour que TypeScript soit utilisé dans le projet. Même si il n’expoite pas toute la puissance du TypeScript, la qualité d’un projet augemente fortement par rapport à ce que je vois en JSX.

Donc, bilan, je suis très attaché au code, et pour ma part le langage importe énormément pour la productivité. React gagne à utiliser ce langage. C’est bien entendu ma vision, mon avis, ma façon de voir les choses. Vous avez tout à fait le droit, et certainement raison, de ressentir les choses autrement, d’avoir d’autres objectifs et une philosophie différente de la mienne. C’est aussi ça la force de notre métier, chers amis.

Vous l’aurez donc compris, mon choix reste sur Angular, puis VueJS, et enfin React. Et surtout que je préfère largement utiliser Typescript. Et je finis sur le positif, React me plait avec Typescript, il peut, potentiellement, être un de mes choix dans des futurs projets à condition d’utiliser TSX.

comments powered by Disqus