Nouveau : Datasets open source gratuits disponibles !Decouvrir →
💚
Intermediaire 30 min Vue

Vue avec GraphQL

Pourquoi Vue avec GraphQL ?

L'adoption de Vue.js avec GraphQL est une pratique courante, notamment dans les applications modernes où la performance et l'évolutivité sont des priorités. Les développeurs peuvent tirer parti de ces technologies pour construire des interfaces utilisateur réactives et efficaces en utilisant un langage de requêtes puissant pour récupérer uniquement les données nécessaires du serveur.

Un cas concret est une application e-commerce où on a besoin de récupérer des détails produits dynamiques, comme la description et les images, ainsi que leurs prix. Avec GraphQL, le client peut demander exactement ces informations, évitant ainsi un surcharge de données inutiles et réduisant le temps de réponse.

Prerequis

  • Connaissances en JavaScript ES6+
  • Familiarité avec Vue.js 2 ou 3
  • Compréhension des bases de l'API REST
  • Accès à un environnement de développement (Node.js)
  • Installation de Git pour versionner le code

Outils à installer

Pour ce tutoriel, nous aurons besoin des outils suivants :

## Node.js v14+
npm install -g @vue/cli@latest

Concepts fondamentaux

1. GraphQL

GraphQL est un langage de requêtes et d'informations pour les APIs. Il permet aux clients d'interroger exactement ce qu'ils ont besoin, sans avoir à récupérer des données supplémentaires.

// Schema GraphQL
type Query {
  hello: String
}

2. Client GraphQL

Un client GraphQL est un outil qui permet de faire des requêtes vers le serveur GraphQL et de gérer la réponse. Vue Apollo est l'un des clients les plus populaires avec Vue.js.

// Installation du client Apollo avec Vue
npm install vue-apollo graphql apollo-client apollo-link-http apollo-cache-inmemory graphql-tag

import { ApolloClient, HttpLink, InMemoryCache } from 'apollo-client';
import { createApolloProvider } from '@vue/apollo-option';

const httpLink = new HttpLink({
  // URL de l'API GraphQL
  uri: 'http://localhost:4000/graphql',
});

const apolloClient = new ApolloClient({
  link: httpLink,
  cache: new InMemoryCache(),
});

const apolloProvider = createApolloProvider({
  defaultClient: apolloClient,
});

3. Queries GraphQL

Une query est une requête HTTP qui récupère des données du serveur. Elle retourne uniquement les champs demandés.

// Une query pour récupérer un utilisateur par son ID
const GET_USER_QUERY = gql`
  query GetUser($id: ID!) {
    user(id: $id) {
      id
      name
      email
    }
  }
`;

4. Mutations GraphQL

Une mutation est une requête HTTP qui modifie les données du serveur, comme la création d'un utilisateur.

// Une mutation pour créer un utilisateur
const CREATE_USER_MUTATION = gql`
  mutation CreateUser($name: String!, $email: String!) {
    createUser(name: $name, email: $email) {
      id
      name
      email
    }
  }
`;

5. Subscriptions GraphQL

Une subscription est une requête HTTP qui permet de recevoir des mises à jour en temps réel du serveur.

// Une subscription pour recevoir les nouvelles tâches
const NEW_TASK_SUBSCRIPTION = gql`
  subscription NewTask {
    newTask {
      id
      title
      description
    }
  }
`;

Mise en pratique : projet fil rouge

Nous allons créer un gestionnaire de tâches simple avec Vue.js et GraphQL. Le projet comprendra les fonctionnalités suivantes :

  1. Afficher la liste des tâches
  2. Ajouter une nouvelle tâche
  3. Supprimer une tâche

Étape 1 : Création du projet Vue

Commencez par créer un nouveau projet Vue :

vue create task-manager
cd task-manager

Étape 2 : Installation des dépendances

Installez les packages nécessaires pour Apollo Client et les outils de développement :

npm install vue-apollo graphql apollo-client apollo-link-http apollo-cache-inmemory graphql-tag @vue/cli-service@latest --save

Étape 3 : Configuration d'Apollo Client

Créez un fichier apollo.js dans le répertoire src et ajoutez la configuration Apollo Client :

// src/apollo.js
import { ApolloClient, HttpLink, InMemoryCache } from 'apollo-client';
import { createApolloProvider } from '@vue/apollo-option';

const httpLink = new HttpLink({
  uri: 'http://localhost:4000/graphql',
});

const apolloClient = new ApolloClient({
  link: httpLink,
  cache: new InMemoryCache(),
});

const apolloProvider = createApolloProvider({
  defaultClient: apolloClient,
});

export default apolloProvider;

Étape 4 : Configuration d'Apollo Provider

Importez et utilisez apolloProvider dans le fichier principal de l'application :

// src/main.js
import Vue from 'vue';
import App from './App.vue';
import router from './router';
import store from './store';
import apolloProvider from './apollo';

Vue.config.productionTip = false;

new Vue({
  provide: apolloProvider.provide(),
  router,
  store,
  render: h => h(App),
}).$mount('#app');

Étape 5 : Création des composants

Créez un composant pour afficher la liste des tâches :

<!-- src/components/TasksList.vue -->
<template>
  <div>
    <h1>Tâches</h1>
    <ul>
      <li v-for="task in tasks" :key="task.id">
        task.title - task.description
        <button @click="deleteTask(task.id)">Supprimer</button>
      </li>
    </ul>
  </div>
</template>

<script>
import { GET_TASKS_QUERY, DELETE_TASK_MUTATION } from '@/graphql';

export default {
  data() {
    return {
      tasks: [],
    };
  },
  apollo: {
    tasks: {
      query: GET_TASKS_QUERY,
      fetchPolicy: 'network-only',
    },
  },
  methods: {
    async deleteTask(id) {
      try {
        await this.$apollo.mutate({
          mutation: DELETE_TASK_MUTATION,
          variables: { id },
        });
      } catch (error) {
        console.error('Erreur lors de la suppression de la tâche', error);
      }
    },
  },
};
</script>

Étape 6 : Création des mutations

Créez un fichier graphql.js pour stocker les queries et mutations :

// src/graphql.js
import gql from 'graphql-tag';

export const GET_TASKS_QUERY = gql`
  query GetTasks {
    tasks {
      id
      title
      description
    }
  }
`;

export const CREATE_TASK_MUTATION = gql`
  mutation CreateTask($title: String!, $description: String!) {
    createTask(title: $title, description: $description) {
      id
      title
      description
    }
  }
`;

export const DELETE_TASK_MUTATION = gql`
  mutation DeleteTask($id: ID!) {
    deleteTask(id: $id)
  }
`;

Étape 7 : Ajout de la fonctionnalité d'ajout de tâche

Ajoutez un composant pour ajouter une nouvelle tâche :

<!-- src/components/AddTask.vue -->
<template>
  <div>
    <h2>Ajouter une tâche</h2>
    <form @submit.prevent="addTask">
      <input v-model="title" placeholder="Titre" required />
      <textarea v-model="description" placeholder="Description"></textarea>
      <button type="submit">Ajouter</button>
    </form>
  </div>
</template>

<script>
import { CREATE_TASK_MUTATION } from '@/graphql';

export default {
  data() {
    return {
      title: '',
      description: '',
    };
  },
  methods: {
    async addTask() {
      try {
        await this.$apollo.mutate({
          mutation: CREATE_TASK_MUTATION,
          variables: { title: this.title, description: this.description },
        });
        this.title = '';
        this.description = '';
      } catch (error) {
        console.error('Erreur lors de l\'ajout de la tâche', error);
      }
    },
  },
};
</script>

Étape 8 : Intégration des composants

Intégrez les composants dans le fichier App.vue :

<!-- src/App.vue -->
<template>
  <div id="app">
    <router-view></router-view>
  </div>
</template>

<script>
export default {
  name: 'App',
};
</script>

Étape 9 : Configuration des routes

Ajoutez les routes pour afficher la liste et ajouter une tâche :

// src/router/index.js
import Vue from 'vue';
import Router from 'vue-router';
import TasksList from '@/components/TasksList.vue';
import AddTask from '@/components/AddTask.vue';

Vue.use(Router);

export default new Router({
  routes: [
    {
      path: '/',
      name: 'TasksList',
      component: TasksList,
    },
    {
      path: '/add-task',
      name: 'AddTask',
      component: AddTask,
    },
  ],
});

Erreurs fréquentes et debugging

Erreur : Cannot read property 'map' of undefined

Cette erreur se produit lorsque la query GraphQL retourne une valeur undefined au lieu d'un objet.

## ❌ Mauvais
<template>
  <div>
    <h1>Tâches</h1>
    <ul v-if="tasks">
      <li v-for="task in tasks" :key="task.id">
        task.title - task.description
      </li>
    </ul>
  </div>
</template>

<script>
import { GET_TASKS_QUERY } from '@/graphql';

export default {
  data() {
    return {
      tasks: [],
    };
  },
  apollo: {
    tasks: {
      query: GET_TASKS_QUERY,
      fetchPolicy: 'network-only',
    },
  },
};
</script>
vue
## ✅ Correct
<template>
  <div>
    <h1>Tâches</h1>
    <ul v-if="tasks && tasks.length">
      <li v-for="task in tasks" :key="task.id">
        task.title - task.description
      </li>
    </ul>
    <p v-else>Aucune tâche trouvée.</p>
  </div>
</template>

<script>
import { GET_TASKS_QUERY } from '@/graphql';

export default {
  data() {
    return {
      tasks: [],
    };
  },
  apollo: {
    tasks: {
      query: GET_TASKS_QUERY,
      fetchPolicy: 'network-only',
    },
  },
};
</script>

Erreur : Cannot read property 'id' of undefined

Cette erreur se produit lorsque la mutation GraphQL retourne une valeur undefined au lieu d'un objet.

## ❌ Mauvais
<template>
  <div>
    <h2>Ajouter une tâche</h2>
    <form @submit.prevent="addTask">
      <input v-model="title" placeholder="Titre" required />
      <textarea v-model="description" placeholder="Description"></textarea>
      <button type="submit">Ajouter</button>
    </form>
  </div>
</template>

<script>
import { CREATE_TASK_MUTATION } from '@/graphql';

export default {
  data() {
    return {
      title: '',
      description: '',
    };
  },
  methods: {
    async addTask() {
      try {
        await this.$apollo.mutate({
          mutation: CREATE_TASK_MUTATION,
          variables: { title: this.title, description: this.description },
        });
        this.title = '';
        this.description = '';
      } catch (error) {
        console.error('Erreur lors de l\'ajout de la tâche', error);
      }
    },
  },
};
</script>
vue
## ✅ Correct
<template>
  <div>
    <h2>Ajouter une tâche</h2>
    <form @submit.prevent="addTask">
      <input v-model="title" placeholder="Titre" required />
      <textarea v-model="description" placeholder="Description"></textarea>
      <button type="submit">Ajouter</button>
    </form>
  </div>
</template>

<script>
import { CREATE_TASK_MUTATION } from '@/graphql';

export default {
  data() {
    return {
      title: '',
      description: '',
    };
  },
  methods: {
    async addTask() {
      try {
        const result = await this.$apollo.mutate({
          mutation: CREATE_TASK_MUTATION,
          variables: { title: this.title, description: this.description },
        });
        if (result.data.createTask) {
          this.title = '';
          this.description = '';
        }
      } catch (error) {
        console.error('Erreur lors de l\'ajout de la tâche', error);
      }
    },
  },
};
</script>

Erreur : Cannot read property 'subscribe' of undefined

Cette erreur se produit lorsque la subscription GraphQL retourne une valeur undefined au lieu d'un objet.

## ❌ Mauvais
<template>
  <div>
    <h1>Nouvelles tâches</h1>
    <ul>
      <li v-for="task in newTasks" :key="task.id">
        task.title - task.description
      </li>
    </ul>
  </div>
</template>

<script>
import { NEW_TASK_SUBSCRIPTION } from '@/graphql';

export default {
  data() {
    return {
      newTasks: [],
    };
  },
  apollo: {
    newTask: {
      query: NEW_TASK_SUBSCRIPTION,
    },
  },
};
</script>
vue
## ✅ Correct
<template>
  <div>
    <h1>Nouvelles tâches</h1>
    <ul>
      <li v-for="task in newTasks" :key="task.id">
        task.title - task.description
      </li>
    </ul>
  </div>
</template>

<script>
import { NEW_TASK_SUBSCRIPTION } from '@/graphql';

export default {
  data() {
    return {
      newTasks: [],
    };
  },
  apollo: {
    newTask: {
      query: NEW_TASK_SUBSCRIPTION,
      subscribeToResult: (result) => ({
        data: result.data.newTask,
      }),
    },
  },
};
</script>

Pour aller plus loin

1. Authentification avec JWT

Pour ajouter une authentification sécurisée à votre application, vous pouvez utiliser JSON Web Tokens (JWT). Cela impliquera la création d'un middleware pour vérifier les tokens et le renouvellement des sessions.

2. Optimisation des requêtes GraphQL

Utilisez les directives @include et @skip pour optimiser les requêtes GraphQL en récupérant uniquement les champs nécessaires.

query GetUser($id: ID!, $withEmail: Boolean) {
  user(id: $id) @include(if: $withEmail) {
    id
    name
    email
  }
}

3. Tests unitaires avec Jest et Vue Test Utils

Écrivez des tests unitaires pour votre application en utilisant Jest et Vue Test Utils. Cela aidera à assurer la qualité du code et à prévenir les bugs futurs.

// src/components/TasksList.spec.js
import { shallowMount } from '@vue/test-utils';
import TasksList from '@/components/TasksList.vue';

describe('TasksList.vue', () => {
  let wrapper;

  beforeEach(() => {
    wrapper = shallowMount(TasksList);
  });

  it('renders a list of tasks', async () => {
    wrapper.vm.$apollo.queries.tasks.loading = false;
    wrapper.vm.$apollo.queries.tasks.result = {
      data: {
        tasks: [
          { id: 1, title: 'Task 1', description: 'Description 1' },
          { id: 2, title: 'Task 2', description: 'Description 2' },
        ],
      },
    };
    await wrapper.vm.$nextTick();
    expect(wrapper.findAll('li')).toHaveLength(2);
  });
});

Conclusion

En suivant ce tutoriel, vous avez appris à créer une application web complète utilisant Vue.js, Vuex, Vue Router et GraphQL. Vous avez également appris comment gérer les queries, mutations et subscriptions GraphQL, ainsi que comment optimiser les requêtes et ajouter des fonctionnalités de sécurité et de tests unitaires.

N'oubliez pas que ce tutoriel ne couvre qu'un aspect basique de la création d'une application avec Vue.js et GraphQL. Il existe de nombreux autres aspects à explorer pour améliorer votre application, comme l'utilisation du cache Apollo, la gestion des erreurs et le développement côté serveur avec Node.js.

Besoin d'aide sur Vue ?

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

Recevoir des conseils

Questions frequentes

Quelle est la différence entre Vue.js et GraphQL ?
Vue.js est une bibliothèque front-end utilisée pour construire l'interface utilisateur des applications web, tandis que GraphQL est un langage de requêtes et d'échanges de données qui permet aux clients de demander exactement les données dont ils ont besoin.
Comment installer Vue CLI et générer un nouveau projet avec GraphQL ?
Pour installer Vue CLI, exécutez la commande `npm install -g @vue/cli`. Ensuite, pour créer un nouveau projet avec GraphQL, vous pouvez utiliser le preset officiel de Vue : `vue create mon-projet --preset vuejs-templates/webpack-graphql`.
Comment accéder aux données depuis une API GraphQL dans une application Vue ?
Pour accéder aux données depuis une API GraphQL dans une application Vue, vous pouvez utiliser des bibliothèques comme `axios` pour les appels HTTP et `apollo-client` ou `vue-apollo` pour gérer les requêtes et la mise à jour de l'état de votre application en fonction des données récupérées.

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.