Programmable Web, client side, 2017-2018

De $1

Version de 23:05, 16 Avr 2024

cette version.

Revenir à liste des archives.

Voir la version actuelle

Introduction

Dans ce cours nous allons voir les tendances du développement d'applications Web côté client: évolutions du développement JavaScript, des différentes APIs standard comme les Web Components, les principaux frameworks JavaScript, les environnements de développement, les évolutions du Web Mobile.

Séance 1: état des lieux des technologies front-end

DOM or not to DOM ?

Ecriture en live coding d'une todo list:

  1. Pur JavaScript + DOM API http://jsbin.com/gaqugic/edit
  2.  Avec jQuery et Lodash : http://jsbin.com/posowem/edit?html,js
  3. Avec vueJS 'simple' : http://jsbin.com/haguven/edit?html,console
  4. Idem mais avec des données obtenues par fetch: http://jsbin.com/bifozud/edit?html,js,console,output
    •  
  5. Requêtes REST: fake APis avec https://jsonplaceholder.typicode.com/, faire des requêtes REST avec XhR2, fetch API, quelques mots sur GraphQL et Appolo 

MOOCs utiles

  • JavaScript introduction par Michel Buffa, gratuit.
     
  • Nombreux tutoriaux sur les spécificités d'ES6 non vues dans le MOOC précédents, sur YouTube, etc. Les bons MOOCS sont payants pour la pluparts, mais nous verrons pas mal de choses en cours.
     
  • On va voir dans ce cours, les principaux frameworks JavaScript : VueJS, React et Angular 5. Il existe de nombreux MOOCs qui les présentent, la plupart payants. Le cours vous donnera une introduction assez complète mais il sera souvent nécessaires de vous référer aux sites Webs et documentations officiels.

Séance 2: WebComponents standard et suite VueJS

Les WebComponents : un standard du W3C

On va dans un premier temps étudier la notion de WebComponents, un standard du W3C basé sur 4 APIs qui sont (ou vont) être implémentées par votre navigateur.

  • Voir la Week 4, section 4.2, du MOOC HTML5 Apps and Games. Inscrivez-vous (gartuitement) au MOOC et allez voir ce chapitre, que nous allons commenter en classe.

Exercice 1 (utilisation de WebComponents récupérés sur le Web): récuperez l'archive suivante : VideoUsingWebComponentsNew.zip, dezippez-la et testez la page Web à l'aide d'un serveut HTTP (par ex WAMP, MAMP ou encore plus pratique, l'extension de navigateur Web browser for Chrome)

Exercice 2 (idem), récuperez l'achive suivante testCircleProgress.zip et testez à l'aide d'un serveur HTTP. Regardez le code source.

A etudier à la maison (cours à venir): le framework Polymer 2 (Google), qui est basé sur les WebComponents, et qui est utilisé par YouTube Gaming par exemple.

Suite de l'étude de VueJS

J'ai rajouté eux exemples vus la semaine dernière, un exemple qui charge des données par fetch/ajax.

Créer des composants avec VueJS

Reprenez un des derniers exemples faits avec VueJS, ma gestion d'une todo list: http://jsbin.com/haguven/edit?html,console,output

Dans cet exemple, on ne peut pas instancier plusieurs "Vues". Mais on peut associer la VueJS à un "faux" élement custom HTML, comme ici: http://jsbin.com/haguven/edit?html,js,console,output

Exercice à faire: inspirez-vous de cet exemple pour gérer une liste de hobbies, mais avec les contraintes indiquées dans les commentaires HTML de ce squelette d'application: http://jsbin.com/guwetoy/edit?html,js,output

Correction (ne regarder qu'après avoir vraiment essayé, ou vu la correction en live conding): http://jsbin.com/guwetoy/1/edit

Développer en mode "CLI" avec un environnement de build/testy

Cette fois-ci, pour terminer l'introduction à VueJS, le plus élégant/simple des trois gros frameworks "industriels" modernes (React, VueJS, Angular), nous allons regarder comment on peut développer avec "un environnement de développement", qu'on appelle "CLI" pour "Command Line Environment". 

Les trois frameworks cités, mais aussi Polymer dont on vient de parler, proposent un environnement "CLI".

Travail à faire :

  1. Installer Vue-cli: exécuter "npm install -g vue-cli", si vous êtes sous Linux ou Mac OS, il se peut que vous deviez faire "sudo npm install -g vue-cli" (essayez d'abord sans le sudo).

    Idem, sous windows il se peut que vous deviez avoir ouvert le terminal DOS en mode "administrateur".
     
  2. Créez un répertoire pour le TP
     
  3. Allez dans ce répertoire en mode ligne de commande, depuis votre terminal
     
  4. On va maintenant créer une application VueJS avec le mode "webpack-simple" (cf la page de doc: https://github.com/vuejs/vue-cli), on peut en effet créer plusieurs types de projets avec vue-cli.

    La commande à exécuter est "vue init webpack-simple nom_de_votre_app", je suggère quelques chose comme nom qui ressemble à "my-app-vue-cli1" par exemple. Vous exécuterez donc la commande : "vue init webpack-simple my-app-vue-cli1"

    Vous devrez alors répondre à un petit questionnaire, en général vous faites "enter", répondez "non" si on vous demande d'utiliser "SAAS" (un pré-processeur CSS comme LESS).

    Cela va créer un sous-répertoire my-app-vue-cli qui contiendra tout ce qu'il faut pour démarrer :
    • Une application exemple,
    • un environnement de développement,
    • Des fichiers de configuration pour webpack etc.
       
  5. Allez dans le répertoire de l'application et faites "npm install" pour installer les dépendances (de l'environnement de développement, et du framework)

     
  6. Exécutez l'application de test avec "npm run dev". Si jamais vous avez une page qui affiche "ERR EMPTY RESPONSE", il se peut que vous deviez changer le port du serveur de dev. Allez dans le fichier webpack.config.js et ajoutez une ligne "port:3000" par exemple, dans la config du devserver.

    Voici ce que j'ai dans ma config:

    devServer: {
        historyApiFallback: true,
        noInfo: true,
        overlay: true,
        port:3000
    },
     
  7. Etudier le code du fichier main.js, index.js et App.vue

  8. Créer un composant User.vue qui affiche le nom d'un utilisateur
    Ici un exemple de code: User.vue

  9. Créer un composant Info.vue qui affiche juste des infos supplémentaires sous forme de <p>, et qui soit LOCAL à User.vue (voir Live Coding)

  10. Ajouter dans App.vue un <p>Ceci est un test<p>. Que fait le CSS de User.vue ? Supprimer l'attribut "scoped" de la balise <style> de User.vue, que se passe-t-il ?
     
  11. En étant sûr d'être dans le répertoire du projet faites "npm install -save vue-router" pour installer le module de routage de vueJS.

  12. Remplacez le template de App.vue par le code suivant et testez:
<template>
  <div id="app">
    Hello {{msg}}

    <div>
      <router-link to="/">Home</router-link>
      <router-link to="/blog">Blog</router-link>
      <router-link to="/compte">compte</router-link>
    </div>

    <router-view></router-view>

    <app-user></app-user>
      <p>Ceci est un test</p>
  </div>
</template>

Correction de l'exercice: VueJSExoCli.zip, faire "npm install" et "npm run dev" une fois dezippé.

Séance 3: premiers pas avec React

Exercices d'introduction, dans une IDE en ligne

On peut faire du react dans JsBin/JsFiddle/CodePen, mais croyez-moi, juste pour de petits exemples !

Exercice à faire en vous aidant des exercices précédents:

Pour vous donner une idée du résultat attendu,voici l'équivalent en VueJS: http://jsbin.com/guwetoy/1/edit?html,output

Je conseille de partir de cet exemple React: le composant en classe ES6

En vous aidant de l'exemple fait en classe en live coding, voud devrez faire incrémentalement, en testant après chaque étape :

  1. Créez <div> et affichez dedans un composant Root avec React (l'App des exemples)
     
  2. Affichez un tableau de hobbies dans ce <div> (foot, tennis, jeux video, etc.) sous la forme d'une liste. Chaque hobby sera un <li>. Vous fournirez des hobbies par défaut.
     
  3. Ajoutez un bouton 'Nouveau Hobby' et un champ input pour saisir le nom du hobbie à rajouter. La liste doit se mettre à jour.
     
  4. Rendez les hobbies clickables pour qu'on puisse les supprimer
     
  5. Un message <p>Hobby supprimé !</p> devra apparaitre lorsqu'un hobby est supprimé
     
  6. Ajoutez un compteur de hobbies (<p>Hobbies: 4</p>) au-dessus de la liste des hobbies, qui indiquera le nombre de hobbies dans la liste.
     
  7. Vous changerez les styles CSS des éléments de la liste pour qu'ils s'affichent en rouge et vert à chaque ligne, en alternance. Vous utiliserez aussi des classes CSS dynamiques pour afficher le compteur en rouge si le nombre de hobbies est supérieur à trois, en vert sinon. 
     
  8. Chaque <li>, chaque hobby, sera maintenant dans un composant <Hobby/> 

ICI UNE CORRECTION: https://codepen.io/w3devcampus/pen/b...m?editors=1010

Exercices avec un environnement "CLI"

Si on va voir la page de facebook sur "how to start with React", il y a un chapitre qui concerne le mode "CLI": https://reactjs.org/docs/add-react-to-a-new-app.html

  1. Vous devez avoir nodeJS correctement installé (node, npm, etc, tout ceci doit fonctionner...)
     
  2. Installez l'extension Google Chrome "React Developer Tools" (https://chrome.google.com/webstore/d...jfkapdkoienihi), elle existe aussi pour Firefox.
     
  3. Installez une bonne fenêtre terminal pour Windows -si vous êtes sous windows comme http://cmder.net/ ou autre (github bash, etc.) si je vous vois avec une fenêtre DOS basique vous allez m'entendre !
     
  4. Installer les packages "babel" et "emmet" si vous êtres sous Sublime Text 3 ou Atom. Ca doit etre ok pour Visual Studio Code, WebStorm etc.
     
  5. Ouvrir la ligne de commande et exécuter la commande "npm install -g create-react-app",
    • Pour vérifier que ça fonctionne, créez un autre répertoire nommé "react_cli" et cd dedans,
    • Executez "create-react-app hello-world" (ça prend du temps, quelques minutes)...
    • Allez dans le répertoire créé (cd hello-world), et faites "npm install" (là aussi, quelques minutes)
    • Exécutez le progralle en tapant "npm start", ça doit ouvrir automatiquement le browser sur le port 3000 et afficher une page avec le logo React qui tourne.
    • Editez le code du fichier src/App.js, changez le texte et sauvez -> la page Web de l'application doit se rafraichir automatiquement.
       
  6. Maintenant on va étudier le code, regardez les fichiers html, js, les configs etc.
     
  7. Essayez de modifier la partie "render" de App.js... hmmm ok. Bon, on va faire un simple composant <Username name="toto"/> qu'on va mettre dans un sous répertoire "components" dans les sources, il va simplement afficher un nom passé en attribut/props dans un paragraphe en couleur. Vous ajouterez dans <App/> Plusieurs instances de ce composant.

Exercice: refaire dans le projet les hobbies en mode CLI !

Séance 4: React suite / FireBase / Fetch + Node + Mongo

Pour ceux qui veulent approfondir React: le cours de Wes Bos (React for Beginners). Dans les vidéos de son cours il construit un magasin de poissons de A jusqu'à Z et montre pas mal de petits trucs: le router React, comment utiliser FireFase, comment héberger dans le cloud etc. Les fichiers pour démarrer le projet, et les corrections sont sur : https://github.com/wesbos/React-For-Beginners-Starter-Files 

La suite logique est d'étudier le "gestionnaire d'états" de React, qui s'appelle Redux, là vous trouverez aussi le cours complet gratuit sur le site de Wes Bos (https://learnredux.com/)

En attendant, on va avancer un peu les exemples vus la semaine dernière (hobbies).

UTILISATION DE FIREBASE:

  1. Voir demo du prof :-)

     
  2. Vous allez le faire vous-même:

ETAPE 1 : Il faut commencer par modifier l'exemple des hobbies pour qu'il fonctionne non pas avec un tableau mais avec un objet. Firebase ne sais synchroniser que des objets, pas des tableaux:

Dans App.js :

   this.state = {
      hobbies : {
        hobby0: 'tennis',
        hobby1: 'golf'
      }
      // ...
    };

 Il faudra modifier plusieurs parties du code en conséquence...

  • addHobbies, removeHobbies...

    Hints: vous pouvez utiliser l'opérateur ES6 ... pour cloner un objet. 
     
  • render (il faudra itérer sur les propriétés d'un objet maintenant, excellent exercice !)

    Hint: Object.keys(this.state.hobbies).map((key, index) => {... }

ETAPE 2 : on va devoir, comme pour les exemples faits avec vueJS, utiliser le "cycle de vie" du composant (https://reactjs.org/docs/react-component.html#the-component-lifecycle), et charger des données distantes depuis FireBase quand le composant est "monté", et aussi fermer la conenxion quand il est "démonté". On va pour cela définir les méthodes 

App.js : 

  componentWillMount() {
    console.log("Will mount")
    // this runs right before the <App> is rendered
  }


  componentWillUnmount() {
  console.log("Will unmount")
    base.removeBinding(this.ref);
  }

  Implémentez ces méthodes et vérifiez bien qu'elles sont appelées...

ETAPE 3 : on va créer une base sur FireBase

  • Allez sur https://firebase.google.com/
     
  • Cliquez sur "accèder à la console"
     
  • Cliquez sur "+" pour ajouter un projet, appelez-le "React-EPU-Firebase" par exemple.
     
  • Cliquez à gauche sur "database" et créer une "realtime database".
     
  • Cliquez ensuite sur "règles" et mettez comme valeur pour les deux champs "true" (aucune authentification), on verra plus tard pour l'authentification.
     
  • Cliquez sur "Publier", ignorer le warning.
     
  • Cliquez à gauche sur "Project Overview", et au milieu de la page sur "Ajouter Firebase à votre application Web", une fenêtre s'ouvre avec des bouts de JS.
     
  • Gardez cet onglet ouvert

ETAPE 4 : on ajoute au projet le code pour se connecter à la base:

Dans votre projet, créez un fichier base.js, et mettez ceci dedans:

import Rebase from 're-base';

const base = Rebase.createClass({
// copier les 3 premières lignes de VOTRE config de votre base !!!
 // NE PRENEZ PAS LES VALEURS QUI SONT ICI !!!
    apiKey: "AIzaSyCW_WJJb16YVDlsdsd9c0YNNGnfdssorzWGFRU2ScU",
    authDomain: "react-epu-firebase.firebaseapp.com",
    databaseURL: "https://react-epu-firebase.firebaseio.com" // pas de , à la fin
});


export default base;


ETAPE 5 : on ajoute le module npm re-base pour "parler à firebase"

On ajoute une ligne à package.json pour installer la lib npm qui va bien:

  "dependencies": {
    "react": "^16.1.1",
    "react-dom": "^16.1.1",
    "react-scripts": "1.0.17",
    "re-base": "2.2.0"// -> ajouter cette ligne, mettez bien 2.2.0 !
  },

 Faites "npm install", ça va installer re-base dans node_modules

ETAPE 6 : on va utiliser re-base pour syncrhoniser l'état du composant, c'est-à dire les hobbies:

Dans App.js:

....
import base from './base';
....

componentWillMount() {
    //alert("toto")
    // this runs right before the <App> is rendered
    this.ref = base.syncState("hobbies", {
      context: this,
      state: 'hobbies'
    });
  }

  componentWillUnmount() {
    base.removeBinding(this.ref);
  }


Etape 7 : testez !

Sauvez, testez. Ouvrez dans un onglet votre base et regardez les données en sync. Ouvrez deux onglets avec l'appli React, regardez...

Fetch / REST / Mongo / Node : quelques recommandations, exemples

On va maintenant faire un petit passage en AJAX via fetch/REST sur un serveur node/mongoDB qui travaille sur la base de données des restaurants.

Je suppose que vous avez sur vos machine les logiciels suivants:

  • Node à jour, npm, ça va de soi...
  • MongoDB récent
  • Un outil d'administration qui tient la route (par exemple: https://studio3t.com/)
  • Que vous avez chargé la base de données test avec la collection "restaurants" (si ce n'est pas le cas: uivre les instructions situées sur cette page. Vous allez devoir récupérer le fichier primer-dataset.json (assez gros, attention, ne pas faire copier/coller, faire click droit/sauver), et exécuter la commande suivante, qui créer une bd "test" et ajoute dedans la collection "restaurants" : mongoimport--dbtest--collectionrestaurants--drop--fileprimer-dataset.json

Peter vous a montré du jQuery je crois (!) pour faire des requêtes Ajax, mais depuis 2012 on a fetch qui fonctionne très bien et qui est standard dans les browsers.

Donc, je vous propose de revenir sur le back end un instant avant d'étudier un front-end qui fait du CRUD via fetch, en respectant les bonnes pratiques:

  • GET, PUT, POST, DELETE pour le CRUD
     
  • Utilisation correcte du driver mongoDB via le module npm mongo
     
  • Envoi de formulaires AJAX pour le PUT, POST, DELETE via FormData (formulaires multipart).

ETUDE DE CODE A L'ECRAN / Live coding. Comment debugguer via la console. Comment tester son code serveur REST/ son code client. Comment coder du fetch et générer un tableau avec l'API du DOM, avec VueJS, etc.

Archive à récupérer pour faire pareil sur votre machine: TPRoutageExpressWithMongoPlainJSFetchAndVueJS.zip 

ETAPE 8 avec React : on va voir un peu node / mongo / fetch puis on essaiera d'afficher la liste des restaurants à la place des hobbies... Ah oui, les restaurants de la base de test de mongoDB !

Séance 5: premiers pas avec Angular (4/5)

TP Partie 1 : création d'une application "squelette"

  1. Installer angular-cli : dans une fenêtre de terminal, tapez la commande "npm install -g @angular/cli" (éventuellement avec "sudo" avant si vous êtes sous Linux ou Mac OS)

  2. Créez un répertoire "exo1Angular" et faites cd dans ce répertoire,
  3. Générez une application "squelette" angular en tapant la commande "ng new angular-framework-intro"
  4. Faites cd angular-framework-intro et ouvrez visual studio code sur ce répertoire (commande "code ." sur Mac)
  5. Faites npm install pour installer les modules nécessaires (pour l'application et pour l'environnement de développement)
  6. Exécutez le projet en lançant la commande ng serve --open dans le répertoire
  7. Ok, maintenant faites "view source" sur la page, que remarquez-vous ? Comparez avec React et VueJS... Qu'en déduisez-vous ? A propos, est-ce qu'on a installé une extension dans le browser ?
  8. Etudions maintenant la structure du projet....

TP Partie 2 : affichage d'une liste d'éléments

  1. Regardez le fichier index.html, remarquez l'élément <app-root></app-root>, est-ce du HTML standard ?
  2. Regardez les fichiers src/app.component.tssrc/app.component.html et src/app.component.css
  3. Modifiez le fichier de templates app.components.html et faites ctrl-s,
  4. Regardez le fichier app.module.ts, Angular va vous obliger à mettre à jour ce fichier très régulièrement.
  5. Maintenant on va effacer le contenu du fichier de template, et on va essayer d'afficher une liste d'éléments : CA SE PASSE EN LIVE CODING (une correction sera postée ici à la fin), utilisation de *ngFor (<li *ngFor="let el of elements">...</li> si elements est la propriété du composant -un tableau de chaines de caractères-), un peu l'équivalent du v-for de VueJS.
  6. Ajout d'un bouton pour ajouter un nouvel élément, utilisation de (click)="expression" comme attribut,
  7. Regardons comment afficher une ligne verte, une ligne rouge, etc. Utilisation de [ngStyle]="{propriété CSS : expression}", écrire une fonction getColor(element) comme dans les exemples qu'on avait fait avec VueJS et React, et l'appeler dans l'expression).

TP partie 3 : création d'un nouveau composant

  • On va créer "manuellement" un nouveau composant intitulé "username", qui sera juste un<li> qui affichera la valeur de la propriété username. Pour cela, créer le fichier "app/username.component.ts, et il doit ressembler à cela:

import { Component, Input } from "@angular/core";

@Component ({
    selector: 'app-username',
    template:`
    <p>{{username}}</p>
    `
})

export class UsernameComponent {
    @Input() username :string;
}

Remarquez qu'on n'a pas utilisé ici de template html séparé, à la place on a mis le template directement sous forme de chaine de caractère entre les caractères `....`

Le @Input sert à définir une propriété qu'on pourra passer via des attributs HTML, c'est l'équivalent des "props" de VueJS et de React.

Maintenant, ajoutez des instances de ce composant dans le template app.components.html:

<app-username [username]="'Michel'"></app-username>

<app-username [username]="'John'"></app-username>

Regardez ce que cela donne.... rien, ouvrez la console de debug...

C'est normal, il faut déclarer le composant dans le fichier app.module.ts (c'est pénible... mais vous verrez qu'on peut automatiser cela en créant les composants avec la ligne de commande)... Ajoutez le composant dans app.module.ts et cela devrait fonctionner.

Maintenant on veut pouvoir cliquer sur un nom et afficher un message dans le template du composant principal. On va faire comme en VueJS : envoyer un événement quand on clique sur le nom.

TP Partie 4 : définition d'un événement qui sera envoyé du composant "fils" vers le composant "père"

  1. Dans le composant (app/username/username.component.ts), définir un événement comme ceci: 
export class UsernameComponent {
    @Input() username :string;
    @Output() userClicked = new EventEmitter<string>(); // définition d'un événement

    onUsernameClicked() {
        this.userClicked.emit(this.username);            // émission de l'événément
    }
}

Et dans le template (app/username/username.component.ts) :

    template:`
       <p (click)="onUsernameClicked()">{{username}}</p>
    `

Ainsi, dans le template du composant (app.component.html) qui instancie ce composant, on pourra écouter l'événement "userClicked" :

<app-username [username]="'Michel1'" (userClicked)="onUserWasClicked($event)"></app-username>
<app-username [username]="'John'"    (userClicked)="onUserWasClicked($event)"></app-username>

Et maintenant on peut écrire la méthode onUserWasClicked(username) dans app.component.ts :

onUserWasClicked(username: string) {
    alert(username);
}

Testez l'application : en cliquant sur un nom, ça doit afficher une alerte avec la valeur associée.

TP Partie 5 : binding bi-directionnel avec [(ngModel)]="nom"

  • Définissez un champs de saisie dans le template pour une propriété "nom" que vous ajouterez dans le fichier .ts de app.component.ts
  • Dans le template, affichez la valeur de cette propriété en-dessous du champs de saisie. 
  • Tapez quelque chose dans le champ de saisie
  • Plus simple qu'en React non ? Ca ressemble au v-model de VueJS non ?

TP Partie 6 : refaire l'exemple des hobbies complet, mais en angular

 En vous aidant de l'exemple précédent : 

  1. Dans le composant app.component (.ts/html/), définissez un tableau de hobbies et affichez-les dans une liste (fournissez quelques hobbies par défaut)
     
  2. Ajoutez un bouton 'Nouveau Hobby'  + un champ <input>. Quand on clique le bouton on ajoutera le hobby et la vue se mettra à jour
     
  3. Rendez chaque hobby clickable. Si on clique un hobby on le supprime 
     
  4. Faites apparaitre un message <p>Hobby supprimé! dans un </p> qui ne sera visible que lorsque au moins un hobby a été supprimé (soyez créatifs! Il y a plusieurs manières de faire)
     
  5. Ajouter un compteur de hobbies (<p>Nombre de Hobbies: ...</p>) au-dessus de la liste des hobbies
     
  6. Changez le style CSS du compteur, selon sa valeur: vert si moins de 3 hobbies, rouge sinon
     
  7. Transformez les éléments <li> en un composant réutilisable <app-hobby>
     
  8. On veut remplit les hobbies au démarrage de l'application en récupérant les hobbies au format JSON sur l'URL : https://my-json-server.typicode.com/...ffa/hobbies/db (au passage, j'ai utilisé les services de jsonplaceholder.typicode.com pour servir un fichier json qui se trouve sur un de mes repository github). LIVE CODING AVEC LE PROF pour voir comment créer un service

TP Partie 7 : exercice de routage avec Router et Route, <router-outlet></router-outlet> et <a routerLink="..."></a>

LIVE CODING !!!

Correction du TP

  • Récupérez cette archive : hobbies_angular.zip et desarchivez-la quelque part,
  • Faites cd dans le répertoire créé,
  • Faites "npm install",
  • Faites "ng serve --open"