Cómo crear una aplicación de chat en veinte minutos

imagen



A mi papá le gusta recordarme que, como ingeniero informático en la década de 1970, " era programador antes de que la programación estuviera de moda ". Incluso mostró viejos guiones de Fortran y COBOL un par de veces. Después de leer este código, puedo decir con seguridad que la programación es definitivamente mejor hoy .



Un sello distintivo de los lenguajes de programación y entornos de desarrollo modernos es cuánto menos código tiene que escribir un desarrollador. Mediante el uso de lenguajes de alto nivel junto con las muchas API disponibles, paquetes de código abierto y servicios de pago, las aplicaciones, incluso aquellas con requisitos complejos, se pueden construir con bastante rapidez.



Una comparación para demostrar la evolución del desarrollo de software es la construcción. Érase una vez, la construcción de cualquier casa comenzó con la tala de árboles en su sitio. Sin embargo, los materiales, herramientas y métodos aparecieron rápidamente para que la construcción se completara más rápido, los objetos se volvieran más fuertes y los trabajadores se liberaran de algunas tareas elementales.



¿Cuántos rascacielos se construirían si los constructores extraen su propio acero?



Los desarrolladores de software, que continúan trabajando hasta el día de hoy, en los albores de sus carreras "cortan sus propios árboles". Al mismo tiempo, las innovaciones sin precedentes de la última década han llevado al hecho de que la industria del software comenzó a desarrollarse de manera muy similar a la construcción.



En pocas palabras, los desarrolladores modernos ahora tienen las herramientas, técnicas y mejores prácticas para completar proyectos más rápido, obtener aplicaciones estables y ahorrar a los desarrolladores tareas de bajo nivel.



Cómo hacer una aplicación de chat



Creemos rápidamente algo que solía llevar días o semanas. Crearemos una aplicación de sala de chat pública que utiliza WebSockets para mensajería en tiempo real.



WebSockets es compatible de forma nativa con todos los navegadores modernos. Sin embargo, nuestro objetivo es descubrir qué herramientas podemos utilizar en el trabajo, no reinventarlas . Teniendo esto en cuenta, utilizaremos las siguientes tecnologías:



  • 8base  - API GraphQL administrada
  • VueJS  - marco de JavaScript


El proyecto de inicio y el archivo README completo se pueden encontrar en este repositorio de GitHub . Si solo desea ver la aplicación terminada, eche un vistazo a la rama de la sala de chat pública.



Además, el video a continuación (en inglés) explica cada paso con más detalle.



Empecemos.



Siete pasos para crear una aplicación de chat:



1. Configuración del proyecto



Clona el proyecto de inicio y ve al directorio de chat grupal. Puedes decidir por ti mismo si usar yarn o npm para instalar las dependencias del proyecto. En cualquier caso, necesitamos todos los paquetes NPM especificados en el archivo package.json.



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


Para interactuar con la API GraphQL, necesitamos configurar tres variables de entorno. Cree un archivo .env.local en el directorio raíz con el siguiente comando, y la aplicación Vue, después de la inicialización, establecerá automáticamente las variables de entorno que agregamos a este archivo. Ambos valores y no deben cambiarse. Solo necesita establecer el valor . Si tiene un espacio de trabajo de 8base que desea usar para crear una aplicación de chat usando nuestro tutorial, actualice el archivo .env.local con su ID de espacio de trabajo. De lo contrario, obtenga el ID del espacio de trabajo siguiendo los pasos 1 y 2 de la guía de inicio rápido de 8base .



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. Importar esquema



Ahora tenemos que preparar el lado del servidor. En la raíz de este repositorio, debería encontrar el archivo chat-schema.json. Para importarlo al espacio de trabajo, solo necesita instalar la línea de comando 8base e iniciar sesión, y luego importar el archivo de esquema.



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


3. Acceso a API



La última tarea del backend es permitir el acceso público a la API GraphQL.



En la consola 8base, vaya a App Services > Roles > Guest. Actualice los permisos establecidos para publicaciones y usuarios para que estén marcados o configurados como Todos los registros (como se muestra en la captura de pantalla a continuación).



La función Invitado determina qué puede hacer el usuario que realiza una solicitud de API no autenticada.



imagen

Editor de roles en la consola 8base.



4. Escribir consultas GraphQL



En este paso, vamos a definir y escribir todas las consultas GraphQL que necesitaremos para nuestro componente de chat. Esto nos ayudará a comprender qué datos leeremos, crearemos y escucharemos (a través de WebSockets) utilizando la API.



El siguiente código debe colocarse en un archivo src / utils / graphql.js. Lea los comentarios sobre cada constante exportada para comprender qué hace cada consulta.




/* 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. Configuración del cliente Apollo para suscripciones



Con nuestras consultas GraphQL escritas, es hora de configurar nuestros módulos API.



Primero, abordemos el cliente API ApolloClientcon sus valores predeterminados requeridos. Para createHttpLinknosotros, proporcionamos nuestro punto final de espacio de trabajo completamente formado. Este código 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,    .


Luego trataremos con el cliente de suscripción usando subscriptions-transport-wsy isomorphic-ws. Este código es un poco más largo que el anterior, por lo que vale la pena tomarse el tiempo para leer los comentarios en el código.



Inicializamos SubscriptionClientusando nuestro punto final de WebSockets y workspaceIden parámetros connectionParams. Luego usamos este subscriptionClienten dos métodos definidos en la exportación predeterminada: subscribe()y close().



subscribenos permite crear nuevas suscripciones con datos y devoluciones de llamada de error. El método de cierre es el que podemos usar para cerrar la conexión cuando salimos del 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. Escribir un componente de Vue



Ahora tenemos todo lo que necesitamos para crear un chat público. Solo queda un componente por escribir GroupChat.vue.



Cargue el componente usando hilo servido y continuemos.



Nota importante: todos tienen su propia idea de la belleza, por lo que solo hice los estilos mínimos necesarios para que el componente sea funcional.



Script de componente



Primero, necesitamos importar nuestros módulos, estilos simples y consultas GraphQL. Todo esto está en el nuestro src / utils.

Declare las siguientes importaciones en formato 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";


Datos de componentes



Podemos definir qué propiedades de datos queremos usar en la función de datos de nuestro componente. Todo lo que necesitamos es una forma de almacenar usuarios de chat, mensajes, el nombre del usuario "actual" y cualquier mensaje que aún no se haya enviado. Estas propiedades se pueden agregar de la siguiente manera:



/* imports ... */

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


Ganchos de ciclo de vida



Nuestros enlaces de ciclo de vida se ejecutan en diferentes puntos de la vida de un componente de Vue. Por ejemplo, cuando se monta o actualiza. En este caso, solo nos interesa la creación y el beforeDestroycomponente. En tales casos, queremos abrir las suscripciones de chat o cerrarlas.



/* ... */

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étodos de componentes



Tenemos que añadir algunos métodos para procesar cada respuesta de llamada / API ( createMessage, addMessage, closeChat, etc.). Todos ellos se almacenarán en el objeto método de nuestro componente.

Es necesario

señalar una cosa: la mayoría de las mutaciones no esperan y no manejan las respuestas. Esto se debe a que tenemos suscripciones que rastrean estas mutaciones. Después de un lanzamiento exitoso, la suscripción procesa los datos del evento.

La mayoría

de estos métodos hablan por sí mismos. De todos modos, lea los comentarios en el siguiente código.



/*  ... */

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: '' } }
  }
},
/*  ... */
}


Plantilla de componente



Por último, pero no menos importante, tenemos un componente GroupChat.vue.

Hay

miles de excelentes tutoriales sobre cómo crear hermosas interfaces de usuario. Este no es uno de ellos.

El siguiente

patrón coincide con los requisitos mínimos para la aplicación de chat. Hacerlo hermoso o no depende de ti. Dicho esto, repasemos rápidamente el marcado clave que hemos implementado aquí.

Como

siempre, lea los comentarios en línea del código.



<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>


Y ahora el chat público está construido. Si lo abre en su red local, puede comenzar a enviar y recibir mensajes. Sin embargo, para demostrar que se trata de un chat grupal real, abra varias ventanas y observe el progreso de la conversación.



7. Conclusión y prueba



En este tutorial, hemos explorado cómo el uso de herramientas de desarrollo modernas nos permite crear aplicaciones del mundo real en minutos.



Espero que también haya aprendido cómo inicializar ApolloClienty SubscriptionClientejecutar consultas, mutaciones y suscripciones GraphQL de manera eficiente en un espacio de trabajo de 8base, así como un poco sobre VueJS.



Ya sea que esté trabajando en un juego móvil, mensajería, aplicaciones de notificación u otros proyectos que requieren datos en tiempo real, las suscripciones son una gran herramienta. Y ahora acabamos de empezar a considerarlos.



Crea una aplicación de chat con 8base



8base es un backend sin servidor llave en mano como servicio creado por desarrolladores para desarrolladores. La plataforma 8base permite a los desarrolladores crear impresionantes aplicaciones en la nube utilizando JavaScript y GraphQL. Obtenga más información sobre la plataforma 8base aquí .



All Articles