Nouveau : Datasets open source gratuits disponibles !Decouvrir →
🔺
Intermediaire 30 min Angular

Angular avec GraphQL

Angular avec GraphQL : Un Tutoriel Intermédiaire en 30 Minutes

Pourquoi Angular avec GraphQL ?

Au quotidien, un développeur Angular peut avoir besoin de récupérer et d'afficher des données complexes à partir de différentes sources, comme une base de données, une API REST ou même une APIGraphQL. Avec le temps, il peut s'apercevoir que ses requêtes HTTP sont devenues plus complexes et nécessitent plus de gestion. C'est là que l'Angular avec GraphQL est le bon choix.

En utilisant GraphQL, un développeur Angular peut récupérer exactement les données dont il a besoin, sans avoir à effectuer plusieurs appels d'API individuels. Ce qui signifie qu'il peut rafraîchir les données en une seule requête. De plus, avec GraphQL, le serveur ne renvoie que les données nécessaires, ce qui réduit la taille des données envoyées et augmente ainsi l'efficacité globale de l'application.

Un cas d'usage concret serait l'affichage d'une liste d'utilisateurs avec leurs informations comme leur nom, email et rôle. Avec une API REST traditionnelle, cela nécessiterait plusieurs requêtes pour obtenir ces informations. Avec GraphQL, il suffit simplement d'effectuer une seule requête pour récupérer toutes les données nécessaires.

Prerequis

  • Connaissance de base d'Angular (version 10+)
  • Connaissance de l'utilisation des services HTTP en Angular
  • Familiarité avec les types et interfaces en TypeScript
  • Node.js installé sur votre ordinateur
  • Un éditeur de code (comme Visual Studio Code)

Concepts fondamentaux

1. GraphQL Server

Un serveur GraphQL est une API qui utilise le langage de requêtes GraphQL pour récupérer des données. Il permet aux clients d'effectuer des requêtes précises et de recevoir uniquement les données nécessaires.

// server.ts
import { ApolloServer, gql } from 'apollo-server';

const typeDefs = gql`
  type User {
    id: ID!
    name: String!
    email: String!
  }

  type Query {
    getUser(id: ID!): User
  }
`;

const resolvers = {
  Query: {
    getUser: (_, { id }) => {
      // Simulate fetching data from a database
      return {
        id,
        name: 'John Doe',
        email: 'john.doe@example.com'
      };
    }
  }
};

const server = new ApolloServer({ typeDefs, resolvers });
server.listen().then(({ url }) => {
  console.log(`🚀 Server ready at ${url}`);
});

2. GraphQL Client

Le client GraphQL est utilisé pour effectuer des requêtes sur le serveur GraphQL et récupérer les données nécessaires.

// app.component.ts
import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'app-root',
  template: `
    <div *ngIf="user">
      ID: user.id<br>
      Name: user.name<br>
      Email: user.email
    </div>
  `
})
export class AppComponent {
  user;

  constructor(private http: HttpClient) {
    this.http.get('http://localhost:4000/graphql', {
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        query: `
          query GetUser($id: ID!) {
            getUser(id: $id) {
              id
              name
              email
            }
          }
        `,
        variables: { id: '1' }
      })
    }).subscribe(data => {
      this.user = data.data.getUser;
    });
  }
}

3. Apollo Client

Apollo Client est une bibliothèque JavaScript qui simplifie la gestion des données GraphQL dans les applications React et Angular.

// app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http';
import { ApolloModule, APOLLO_OPTIONS } from 'apollo-angular';
import { HttpLinkModule, HttpLink } from 'apollo-angular-link-http';
import { InMemoryCache } from 'apollo-cache-inmemory';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule,
    ApolloModule,
    HttpLinkModule
  ],
  providers: [
    {
      provide: APOLLO_OPTIONS,
      useFactory: (httpLink: HttpLink) => {
        return {
          link: httpLink.create({
            uri: 'http://localhost:4000/graphql'
          }),
          cache: new InMemoryCache()
        };
      },
      deps: [HttpLink]
    }
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }
typescript
// app.component.ts
import { Component } from '@angular/core';
import { Apollo } from 'apollo-angular';

@Component({
  selector: 'app-root',
  template: `
    <div *ngIf="user">
      ID: user.id<br>
      Name: user.name<br>
      Email: user.email
    </div>
  `
})
export class AppComponent {
  user;

  constructor(private apollo: Apollo) {
    this.apollo.watchQuery({
      query: gql`
        query GetUser($id: ID!) {
          getUser(id: $id) {
            id
            name
            email
          }
        }
      `,
      variables: { id: '1' }
    }).valueChanges.subscribe(data => {
      this.user = data.data.getUser;
    });
  }
}

Mise en pratique : Projet fil rouge

Étape 1 : Création du projet Angular

ng new angular-graphql-app
cd angular-graphql-app

Étape 2 : Installation d'Apollo Client

npm install apollo-angular apollo-angular-link-http apollo-cache-inmemory graphql-tag graphql

Étape 3 : Configuration d'Apollo Client

Créez un fichier apollo.config.ts dans le dossier src/environments/.

// src/environments/environment.ts
export const environment = {
  production: false,
  apiUrl: 'http://localhost:4000/graphql'
};

Étape 4 : Configuration de l'application

Modifiez app.module.ts pour inclure Apollo Client.

// app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http';
import { ApolloModule, APOLLO_OPTIONS } from 'apollo-angular';
import { HttpLinkModule, HttpLink } from 'apollo-angular-link-http';
import { InMemoryCache } from 'apollo-cache-inmemory';

import { AppComponent } from './app.component';
import { environment } from '../environments/environment';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule,
    ApolloModule,
    HttpLinkModule
  ],
  providers: [
    {
      provide: APOLLO_OPTIONS,
      useFactory: (httpLink: HttpLink) => {
        return {
          link: httpLink.create({
            uri: environment.apiUrl
          }),
          cache: new InMemoryCache()
        };
      },
      deps: [HttpLink]
    }
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

Étape 5 : Création d'un service GraphQL

Créez un fichier user.service.ts dans le dossier src/app/.

// src/app/user.service.ts
import { Injectable } from '@angular/core';
import { Apollo, gql } from 'apollo-angular';

@Injectable({
  providedIn: 'root'
})
export class UserService {
  constructor(private apollo: Apollo) {}

  getUser(id: string) {
    return this.apollo.watchQuery<any>({
      query: gql`
        query GetUser($id: ID!) {
          getUser(id: $id) {
            id
            name
            email
          }
        }
      `,
      variables: { id }
    }).valueChanges;
  }
}

Étape 6 : Création d'un composant pour afficher les utilisateurs

Créez un fichier user.component.ts et user.component.html dans le dossier src/app/.

// src/app/user.component.ts
import { Component, OnInit } from '@angular/core';
import { UserService } from './user.service';

@Component({
  selector: 'app-user',
  templateUrl: './user.component.html',
  styleUrls: ['./user.component.css']
})
export class UserComponent implements OnInit {
  user;

  constructor(private userService: UserService) {}

  ngOnInit() {
    this.userService.getUser('1').subscribe(data => {
      this.user = data.data.getUser;
    });
  }
}
html
<!-- src/app/user.component.html -->
<div *ngIf="user">
  ID: user.id<br>
  Name: user.name<br>
  Email: user.email
</div>

Étape 7 : Ajout du composant à la route

Modifiez app-routing.module.ts pour ajouter une route pour le composant UserComponent.

// src/app/app-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { UserComponent } from './user/user.component';

const routes: Routes = [
  { path: 'user/:id', component: UserComponent }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

Étape 8 : Ajout de la route à l'application

Modifiez app.component.html pour ajouter une barre de navigation avec une route vers le composant UserComponent.

<!-- src/app/app.component.html -->
<nav>
  <a routerLink="/user/1">User</a>
</nav>

<router-outlet></router-outlet>

Erreurs fréquentes et debugging

1. Erreur : Syntaxe de la requête GraphQL incorrecte

## ❌ Mauvais
query {
  getUser(id: "1")
}

## ✅ Correct
query GetUser($id: ID!) {
  getUser(id: $id) {
    id
    name
    email
  }
}

2. Erreur : Le serveur GraphQL est inaccessible

## ❌ Mauvais
const server = new ApolloServer({ typeDefs, resolvers });
server.listen().then(({ url }) => {
  console.log(`🚀 Server ready at ${url}`);
});

## ✅ Correct
const server = new ApolloServer({ typeDefs, resolvers });
server.listen().catch(err => {
  console.error('Server failed to start', err);
});

3. Erreur : Le client GraphQL ne peut pas se connecter au serveur

## ❌ Mauvais
this.http.get('http://localhost:4000/graphql', {
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    query: `
      query GetUser($id: ID!) {
        getUser(id: $id) {
          id
          name
          email
        }
      }
    `,
    variables: { id: '1' }
  })
}).subscribe(data => {
  this.user = data.data.getUser;
});

## ✅ Correct
this.http.post('http://localhost:4000/graphql', {
  query: `
    query GetUser($id: ID!) {
      getUser(id: $id) {
        id
        name
        email
      }
    }
  `,
  variables: { id: '1' }
}, {
  headers: { 'Content-Type': 'application/json' }
}).subscribe(data => {
  this.user = data.data.getUser;
});

Pour aller plus loin

1. Optimisation des requêtes GraphQL avec le batching

Le batching permet de regrouper plusieurs requêtes en une seule requête pour améliorer les performances.

// server.ts
const server = new ApolloServer({
  typeDefs,
  resolvers,
  context: ({ req }) => {
    return { token: req.headers.authorization };
  },
  plugins: [
    ApolloServerPluginBatchHttp()
  ]
});

2. Authentification et autorisation avec GraphQL

L'authentification et l'autorisation sont essentiels pour protéger les données sensibles.

// server.ts
const server = new ApolloServer({
  typeDefs,
  resolvers,
  context: ({ req }) => {
    const token = req.headers.authorization;
    return { user: jwt.verify(token, 'secret') };
  },
  plugins: [
    ApolloServerPluginAuthentication({
      getUser: async (ctx) => {
        const token = ctx.req.headers.authorization;
        if (token) {
          try {
            return await jwt.verify(token, 'secret');
          } catch (e) {}
        }
        return null;
      }
    })
  ]
});

3. Utilisation de directives GraphQL

Les directives permettent d'ajouter des fonctionnalités spécifiques aux requêtes GraphQL.

// schema.graphql
directive @cacheControl(maxAge: Int!) on FIELD_DEFINITION

type User {
  id: ID!
  name: String!
  email: String! @cacheControl(maxAge: 3600)
}

Défi pratique : Créer un service pour récupérer des tâches à faire

Créez un service task.service.ts qui utilise GraphQL pour récupérer et gérer les tâches à faire. Ajoutez une méthode pour obtenir toutes les tâches, une méthode pour ajouter une nouvelle tâche et une méthode pour marquer une tâche comme terminée.

// src/app/task.service.ts
import { Injectable } from '@angular/core';
import { Apollo, gql } from 'apollo-angular';

@Injectable({
  providedIn: 'root'
})
export class TaskService {
  constructor(private apollo: Apollo) {}

  getTasks() {
    return this.apollo.watchQuery<any>({
      query: gql`
        query GetTasks {
          tasks {
            id
            title
            description
            completed
          }
        }
      `
    }).valueChanges;
  }

  addTask(title: string, description: string) {
    return this.apollo.mutate({
      mutation: gql`
        mutation AddTask($title: String!, $description: String!) {
          addTask(title: $title, description: $description) {
            id
            title
            description
            completed
          }
        }
      `,
      variables: { title, description },
      refetchQueries: ['GetTasks']
    });
  }

  completeTask(id: string) {
    return this.apollo.mutate({
      mutation: gql`
        mutation CompleteTask($id: ID!) {
          completeTask(id: $id) {
            id
            title
            description
            completed
          }
        }
      `,
      variables: { id },
      refetchQueries: ['GetTasks']
    });
  }
}

Ce tutoriel vous a montré comment utiliser Angular avec GraphQL pour récupérer et afficher des données complexes. Vous avez appris les concepts de base de GraphQL, comment configurer Apollo Client dans une application Angular, et comment créer un service pour gérer des données en utilisant GraphQL. Vous devriez maintenant être capable de créer des applications plus efficaces et performantes en utilisant Angular avec GraphQL.

Besoin d'aide sur Angular ?

Besoin d'aide sur un projet technique ? Decrivez-le pour des conseils personnalises.

Recevoir des conseils

Questions frequentes

Qu'est-ce que GraphQL?
GraphQL est une requête d'API qui permet aux clients de demander exactement les données dont ils ont besoin, tout en minimisant le nombre de requêtes.
Comment configurer Angular avec GraphQL?
Pour configurer Angular avec GraphQL, vous devez installer le package 'apollo-angular' et 'apollo-client-preset'. Ensuite, vous pouvez initialiser ApolloClient dans votre application Angular en configurant les serveurs de données.
Comment optimiser les requêtes GraphQL?
Pour optimiser les requêtes GraphQL, vous pouvez utiliser la pagination, le filtri et le tri pour récupérer uniquement les données nécessaires. De plus, vous pouvez utiliser le caching pour éviter les requêtes supplémentaires.

Pages liees

Chaque semaine, le meilleur de la tech francaise

Tendances, salaires, outils et opportunites — directement dans votre boite mail.

Gratuit. Desabonnement en un clic. Pas de spam.