Comment créer une application de chat en vingt minutes

image



Mon père aime à me rappeler qu'en tant qu'ingénieur en informatique dans les années 1970, " il était programmeur avant que la programmation ne soit à la mode ". Il a même montré à plusieurs reprises d'anciens scripts Fortran et COBOL. Après avoir lu ce code, je peux affirmer avec confiance que la programmation est définitivement plus cool aujourd'hui .



Une caractéristique des langages de programmation et des environnements de développement modernes est la quantité de code qu'un développeur doit écrire en moins. En utilisant des langages de haut niveau ainsi que les nombreuses API disponibles, les packages open source et les services payants, les applications, même celles avec des exigences complexes, peuvent être créées assez rapidement.



Une comparaison pour démontrer l'évolution du développement logiciel est la construction. Il était une fois, la construction de n'importe quelle maison a commencé par l'abattage d'arbres sur votre site. Cependant, les matériaux, les outils et les méthodes sont rapidement apparus, de sorte que la construction a été achevée plus rapidement, les objets sont devenus plus solides et les travailleurs ont été libérés de certaines tâches élémentaires.



Combien de gratte-ciel seraient construits si les constructeurs exploitaient leur propre acier?



Les développeurs de logiciels, qui continuent à travailler à ce jour, à l'aube de leur carrière "coupent leurs propres arbres". Dans le même temps, des innovations sans précédent de la dernière décennie ont conduit au fait que l'industrie du logiciel a commencé à se développer à peu près de la même manière que la construction.



En termes simples, les développeurs d'aujourd'hui disposent désormais des outils, des techniques et des meilleures pratiques pour mener à bien des projets plus rapidement, obtenir des applications stables et éviter aux développeurs des tâches de bas niveau.



Comment créer une application de chat



Créons rapidement quelque chose qui prenait des jours ou des semaines. Nous allons créer une application Public Chat Room qui utilise WebSockets pour la messagerie en temps réel.



Les WebSockets sont pris en charge nativement par tous les navigateurs modernes. Cependant, notre objectif est de découvrir quels outils nous pouvons utiliser au travail, pas de les réinventer . Dans cette optique, nous utiliserons les technologies suivantes:





Le projet de démarrage et le fichier README complet se trouvent dans ce référentiel GitHub . Si vous ne voulez voir que l'application terminée, jetez un œil à la branche public-chat-room.



De plus, la vidéo ci-dessous (en anglais) explique chaque étape plus en détail.



Commençons.



Sept étapes pour créer une application de chat:



1. Configuration du projet



Clonez le projet de démarrage et accédez au répertoire de discussion de groupe. Vous pouvez décider vous-même d'utiliser yarn ou npm pour installer les dépendances de projet. Dans tous les cas, nous avons besoin de tous les packages NPM spécifiés dans le fichier package.json.



#  
git clone https://github.com/8base/Chat-application-using-GraphQL-Subscriptions-and-Vue.git group-chat
#   
cd group-chat
#  
yarn


Pour interagir avec l'API GraphQL, nous devons configurer trois variables d'environnement. Créez un fichier .env.local dans le répertoire racine avec la commande suivante, et l'application Vue, après l'initialisation, définira automatiquement les variables d'environnement que nous avons ajoutées à ce fichier. Les deux valeurs et ne doivent pas être modifiées. Il vous suffit de définir la valeur . Si vous disposez d'un espace de travail 8base que vous souhaitez utiliser pour créer une application de chat à l'aide de notre didacticiel, mettez à jour le fichier .env.local avec votre ID d'espace de travail. Sinon, obtenez l'ID de l'espace de travail en suivant les étapes 1 et 2 de 8base Quickstart .



echo 'VUE_APP_8BASE_WORKSPACE_ID=<YOUR_8BASE_WORKSPACE_ID>

VUE_APP_8BASE_API_ENDPOINT=https://api.8base.com

VUE_APP_8BASE_WS_ENDPOINT=wss://ws.8base.com' \

> .env.local




VUE_APP_8BASE_API_ENDPOINTVUE_APP_8BASE_WS_ENDPOINTVUE_APP_8BASE_WORKSPACE_ID







2. Importer le schéma



Nous devons maintenant préparer le côté serveur. À la racine de ce référentiel, vous devriez trouver le fichier chat-schema.json. Pour l'importer dans l'espace de travail, il vous suffit d'installer la ligne de commande 8base et de vous connecter, puis d'importer le fichier de schéma.



#  8base CLI
yarn global add 8base-cli
#  CLI
8base login
#      
8base import -f chat-schema.json -w <YOUR_8BASE_WORKSPACE_ID>


3. Accès API



La dernière tâche du backend est d'autoriser l'accès public à l'API GraphQL.



Dans la console 8base, accédez à App Services > Roles > Guest. Mettez à jour les autorisations définies pour les publications et les utilisateurs afin qu'elles soient vérifiées ou définies comme Tous les enregistrements (comme indiqué dans la capture d'écran ci-dessous).



Le rôle Invité détermine ce que l'utilisateur qui effectue une demande d'API non authentifiée est autorisé à faire.



image

Éditeur de rôle dans la console 8base.



4. Écriture de requêtes GraphQL



Dans cette étape, nous allons définir et écrire toutes les requêtes GraphQL dont nous aurons besoin pour notre composant de chat. Cela nous aidera à comprendre quelles données nous allons lire, créer et écouter (via WebSockets) à l'aide de l'API.



Le code suivant doit être placé dans un fichier src / utils / graphql.js. Lisez les commentaires au-dessus de chaque constante exportée pour comprendre ce que fait chaque requête.




/* gql      graphQL */
import gql from "graphql-tag";
‍
/* 1.    -   10  */
export const InitialChatData = gql`
{
  usersList {
    items {
      id
      email
    }
  }
  messagesList(last: 10) {
    items {
      content
      createdAt
      author {
        id
        email
      }
    }
  }
}
`;
‍
/* 2.          */
export const CreateUser = gql`
mutation($email: String!) {
  userCreate(data: { email: $email, roles: { connect: { name: "Guest" } } }) {
    id
  }
}
`;
‍
/* 3.   */
export const DeleteUser = gql`
mutation($id: ID!) {
  userDelete(data: { id: $id, force: true }) {
    success
  }
}
`;
‍
/* 4.        */
export const UsersSubscription = gql`
subscription {
  Users(filter: { mutation_in: [create, delete] }) {
    mutation
    node {
      id
      email
    }
  }
}
`;
‍
/* 5.          */
export const CreateMessage = gql`
mutation($id: ID!, $content: String!) {
  messageCreate(
    data: { content: $content, author: { connect: { id: $id } } }
  ) {
    id
  }
}
`;
‍
/* 6.     . */
export const MessagesSubscription = gql`
subscription {
  Messages(filter: { mutation_in: create }) {
    node {
      content
      createdAt
      author {
        id
        email
      }
    }
  }
}
`;




5. Configuration du client Apollo pour les abonnements



Avec nos requĂŞtes GraphQL Ă©crites, il est temps de configurer nos modules API.



Tout d'abord, abordons le client API ApolloClientavec ses valeurs par défaut requises. Pour createHttpLinknous, nous fournissons notre point de terminaison d'espace de travail entièrement formé. Ce code est en src/utils/api.js.



import { ApolloClient } from "apollo-boost";
import { createHttpLink } from "apollo-link-http";
import { InMemoryCache } from "apollo-cache-inmemory";
‍
const { VUE_APP_8BASE_API_ENDPOINT, VUE_APP_8BASE_WORKSPACE_ID } = process.env;

export default new ApolloClient({
link: createHttpLink({
  uri: `${VUE_APP_8BASE_API_ENDPOINT}/${VUE_APP_8BASE_WORKSPACE_ID}`,
}),
cache: new InMemoryCache(),
});

// Note:     ,    // ApolloClient,    .


Ensuite, nous traiterons le client d'abonnement en utilisant subscriptions-transport-wset isomorphic-ws. Ce code est un peu plus long que le précédent, il vaut donc la peine de prendre le temps de lire les commentaires dans le code.



Nous initialisons en SubscriptionClientutilisant notre point de terminaison WebSockets et workspaceIddans les paramètres connectionParams. Nous utilisons ensuite celui-ci subscriptionClientdans deux méthodes définies dans l'export par défaut: subscribe()et close().



subscribenous permet de créer de nouveaux abonnements avec des rappels de données et d'erreur. La méthode close est ce que nous pouvons utiliser pour fermer la connexion lorsque nous quittons le chat.



import WebSocket from "isomorphic-ws";
import { SubscriptionClient } from "subscriptions-transport-ws";
‍
const { VUE_APP_8BASE_WS_ENDPOINT, VUE_APP_8BASE_WORKSPACE_ID } = process.env;

/**
*   ,  
*     .
*/

const subscriptionClient = new SubscriptionClient(
VUE_APP_8BASE_WS_ENDPOINT,
{
  reconnect: true,
  connectionParams: {
    /**
      * Workspace ID    ,  
*  Websocket  
*    
      */
    workspaceId: VUE_APP_8BASE_WORKSPACE_ID,
  },
},
/**
  *    WebSocket,   W3C. * ,        *WebSocket (,   NodeJS)
  */
WebSocket
);
‍
export default {
/**
  *   ,      *'data’  'error’
  */
subscribe: (query, options) => {
  const { variables, data, error } = options;
‍
  /**
    *     .
    */
  const result = subscriptionClient.request({
    query,
    variables,
  });
‍
  /**
    *       * ,     , 
* subscriptionClient
    */
  const { unsubscribe } = result.subscribe({
    /**
      *       
* ,  .
      */
    next(result) {
      if (typeof data === "function") {
        data(result);
      }
    },
    /**
      *          ,  .
      */
    error(e) {
      if (typeof error === "function") {
        error(e);
      }
    },
  });
‍
  return unsubscribe;
},
‍
/**
  *  subscriptionClient .
  */
close: () => {
  subscriptionClient.close();
},
};
// .     SubscriptionClient   , 
// ,    .


6. Ecriture d'un composant Vue



Nous avons maintenant tout ce dont nous avons besoin pour créer un chat public. Il ne reste qu'un seul composant à écrire GroupChat.vue.



Chargez le composant en utilisant le service de fil et continuons.



Note importante: chacun a sa propre idée de la beauté, donc je n'ai fait que les styles minimaux nécessaires pour que le composant soit fonctionnel.



Script de composant



Tout d'abord, nous devons importer nos modules, styles simples et requĂŞtes GraphQL. Tout cela est dans le nĂ´tre src / utils.

DĂ©clarez les importations suivantes dans GroupChat.vue.



/* API  */
import Api from "./utils/api";
import Wss from "./utils/wss";

/* graphQL  */
import {
InitialChatData,
CreateUser,
DeleteUser,
UsersSubscription,
CreateMessage,
MessagesSubscription,
} from "./utils/graphql";
‍
/*  */
import "../assets/styles.css";


Données des composants



Nous pouvons définir les propriétés de données que nous voulons utiliser dans la fonction de données de notre composant. Tout ce dont nous avons besoin est un moyen de stocker les utilisateurs du chat, les messages, le nom de l'utilisateur "actuel" et tout message qui n'a pas encore été envoyé. Ces propriétés peuvent être ajoutées comme suit:



/* imports ... */

export default {
name: "GroupChat",
‍
data: () => ({
  messages: [],
  newMessage: "",
  me: { email: "" },
  users: [],
}),
};


Crochets de cycle de vie



Nos hooks de cycle de vie s'exécutent à différents moments de la vie d'un composant Vue. Par exemple, lorsqu'il est monté ou mis à jour. Dans ce cas, nous ne nous intéressons qu'à la création et au beforeDestroycomposant. Dans de tels cas, nous souhaitons soit ouvrir les abonnements au chat, soit les fermer.



/* ... */

export default {
/*   ... */

/**
  *   ,    .
  */
created() {
  /**
    *   ,       
    */
  Wss.subscribe(UsersSubscription, {
    data: this.handleUser,
  });
  /**
    *   ,     
    */
  Wss.subscribe(MessagesSubscription, {
    data: this.addMessage,
  });
  /**
    *     (   10 )
    */
  Api.query({
    query: InitialChatData,
  }).then(({ data }) => {
    this.users = data.usersList.items;
    this.messages = data.messagesList.items;
  });
  /**
    *     ,   
    */
  window.onbeforeunload = this.closeChat;
},
‍
/**
  *   ,    .
  */
beforeDestroy() {
  this.closeChat();
},
};


MĂ©thodes des composants



Nous devons ajouter quelques méthodes pour traiter chaque réponse appel / API ( createMessage, addMessage, closeChat, etc.). Tous seront stockés dans l'objet méthode de notre composant.

Il faut

noter une chose: la plupart des mutations n'attendent pas et ne gèrent pas les réponses. C'est parce que nous avons des abonnements qui suivent ces mutations. Après un lancement réussi, les données d'événement sont traitées par l'abonnement.

La plupart

de ces méthodes parlent d'elles-mêmes. Quoi qu'il en soit, lisez les commentaires dans le code suivant.



/*  ... */

export default {
/*   ... */
‍
methods: {
  /**
    *   ,     .
    */
  createUser() {
    Api.mutate({
      mutation: CreateUser,
      variables: {
        email: this.me.email,
      },
    });
  },
  /**
    *     ID.
    */
  deleteUser() {
    Api.mutate({
      mutation: DeleteUser,
      variables: { id: this.me.id },
    });
  },
  /**
    *        ,   
*           
* .
*
*    ,      ,  
*   ,   .
    */
  handleUser({
    data: {
      Users: { mutation, node },
    },
  }) {
    ({
      create: this.addUser,
      delete: this.removeUser,
    }[mutation](node));
  },
  /**
    *      users,  , *     .
    */
  addUser(user) {
    if (this.me.email === user.email) {
      this.me = user;
    }
    this.users.push(user);
  },
  /**
    *     users  ID.
    */
  removeUser(user) {
    this.users = this.users.filter(
      (p) => p.id != user.id
    );
  },
  /*    */
  createMessage() {
    Api.mutate({
      mutation: CreateMessage,
      variables: {
        id: this.me.id,
        content: this.newMessage,
      },
    }).then(() => (this.newMessage = ""));
  },
  /**
    *        .  * ,    ,       *.
    */
  addMessage({
    data: {
      Messages: { node },
    },
  }) {
    this.messages.push(node);
  },
  /**
    *        .          beforeDestroy     .
    */
  closeChat () {
    /*     */
    Wss.close()
    /*   */
    this.deleteUser();
    /*     */
    this.me = { me: { email: '' } }
  }
},
‍
/*  ... */
}


Modèle de composant



Dernier point mais non le moindre, nous avons un composant GroupChat.vue.

Il existe des

milliers d'excellents tutoriels sur la création de superbes interfaces utilisateur. Ce n'est pas l'un d'eux.

Le

modèle suivant Le rendre beau ou pas, c'est à vous. Cela dit, passons rapidement en revue le balisage clé que nous avons implémenté ici.

Comme

toujours, lisez les commentaires en ligne sur le code.



<template>
<div id="app">
  <!--
           ,     .      ..
    -->
  <div v-if="me.id" class="chat">
    <div class="header">
      <!--
           ,      ,  ,     ,   .
        -->
      {{ users.length }} Online Users
      <!--
           ,   closeChat..
        -->
      <button @click="closeChat">Leave Chat</button>
    </div>
    <!--
     ,      ,      div.  ,         ,     me.
      -->
    <div
      :key="index"
      v-for="(msg, index) in messages"
      :class="['msg', { me: msg.participant.id === me.id }]"
    >
      <p>{{ msg.content }}</p>
      <small
        ><strong>{{ msg.participant.email }}</strong> {{ msg.createdAt
        }}</small
      >
    </div>
    <!--
      newMessage.
      -->
    <div class="input">
      <input
        type="text"
        placeholder="Say something..."
        v-model="newMessage"
      />
      <!--
           ,    createMessage.
        -->
      <button @click="createMessage">Send</button>
    </div>
  </div>
  <!--
          .     ,   createUser.
    -->
  <div v-else class="signup">
    <label for="email">Sign up to chat!</label>
    <br />
    <input
      type="text"
      v-model="me.email"
      placeholder="What's your email?"
      @blur="createUser"
      required
    />
  </div>
</div>
</template>


Et maintenant, le chat public est construit. Si vous l'ouvrez sur votre réseau local, vous pouvez commencer à envoyer et à recevoir des messages. Cependant, pour prouver qu'il s'agit d'une vraie discussion de groupe, ouvrez plusieurs fenêtres et regardez la progression de la conversation.



7. Conclusion et tests



Dans ce didacticiel, nous avons exploré comment l'utilisation d'outils de développement modernes nous permet de créer des applications du monde réel en quelques minutes.



J'espère que vous avez également appris à initialiser ApolloClientet à SubscriptionClientexécuter efficacement des requêtes, des mutations et des abonnements GraphQL dans un espace de travail 8base, ainsi qu'un peu plus sur VueJS.



Que vous travailliez sur un jeu mobile, des messageries instantanées, des applications de notification ou d'autres projets nécessitant des données en temps réel, les abonnements sont un excellent outil. Et maintenant, nous commençons à peine à les considérer.



Créez une application de chat avec 8base



8base est un backend sans serveur clé en main en tant que service conçu par des développeurs pour des développeurs. La plateforme 8base permet aux développeurs de créer des applications cloud époustouflantes à l'aide de JavaScript et GraphQL. En savoir plus sur la plateforme 8base ici .



All Articles