
Meu pai gosta de me lembrar que, como engenheiro de computação na década de 1970, " ele era um programador antes de a programação estar na moda ". Ele até mostrou antigos scripts Fortran e COBOL algumas vezes. Depois de ler este código, posso dizer com segurança que a programação é definitivamente mais legal hoje .
Uma marca registrada das linguagens de programação e ambientes de desenvolvimento modernos é quanto menos código um desenvolvedor precisa escrever. Usando linguagens de alto nível junto com as muitas APIs disponíveis, pacotes de código aberto e serviços pagos, os aplicativos - mesmo aqueles com requisitos complexos - podem ser construídos com bastante rapidez.
Uma comparação para demonstrar a evolução do desenvolvimento de software é a construção. Era uma vez, a construção de qualquer casa começava com o corte de árvores em seu site. No entanto, materiais, ferramentas e métodos apareceram rapidamente para que a construção fosse concluída mais rapidamente, os objetos se tornassem mais fortes e os trabalhadores fossem libertados de algumas tarefas elementares.
Quantos arranha-céus seriam construídos se os construtores extraíssem seu próprio aço?
Os desenvolvedores de software, que continuam trabalhando até hoje, no início de suas carreiras "cortam suas próprias árvores". Ao mesmo tempo, inovações sem precedentes da última década levaram ao fato de que a indústria de software começou a se desenvolver da mesma forma que a construção.
Simplificando, os desenvolvedores modernos agora têm as ferramentas, técnicas e práticas recomendadas para concluir projetos mais rapidamente, obter aplicativos estáveis e salvar os desenvolvedores de tarefas de baixo nível.
Como fazer um aplicativo de chat
Vamos criar rapidamente algo que costumava levar dias ou semanas. Faremos um aplicativo de sala de chat pública que usa WebSockets para mensagens em tempo real.
WebSockets são nativamente suportados por todos os navegadores modernos. No entanto, nosso objetivo é descobrir quais ferramentas podemos usar no trabalho, não reinventá-las . Com isso em mente, usaremos as seguintes tecnologias:
- 8base - API GraphQL gerenciada
- VueJS - framework JavaScript
O projeto inicial e o arquivo README completo podem ser encontrados neste repositório GitHub . Se você quiser apenas ver o aplicativo concluído, dê uma olhada na ramificação da sala de bate-papo pública.
Além disso, o vídeo abaixo (em inglês) explica cada etapa com mais detalhes.
Vamos começar.
Sete etapas para criar um aplicativo de chat:
1. Configuração do projeto
Clone o projeto inicial e vá para o diretório do chat em grupo. Você pode decidir por si mesmo se usará yarn ou npm para instalar dependências do projeto. Em qualquer caso, precisamos de todos os pacotes NPM especificados no arquivo package.json.
#
git clone https://github.com/8base/Chat-application-using-GraphQL-Subscriptions-and-Vue.git group-chat
#
cd group-chat
#
yarn
Para interagir com a API GraphQL, precisamos configurar três variáveis de ambiente. Crie um arquivo .env.local no diretório raiz com o seguinte comando e o aplicativo Vue, após a inicialização, definirá automaticamente as variáveis de ambiente que adicionamos a este arquivo. Ambos os valores e não devem ser alterados. Você só precisa definir o valor . Se você tiver um espaço de trabalho 8base que deseja usar para criar um aplicativo de bate-papo usando nosso tutorial, atualize o arquivo .env.local com seu ID de espaço de trabalho. Caso contrário, obtenha o ID do espaço de trabalho seguindo as etapas 1 e 2 do 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_ENDPOINT
VUE_APP_8BASE_WS_ENDPOINT
VUE_APP_8BASE_WORKSPACE_ID
2. Importar esquema
Agora precisamos preparar o lado do servidor. Na raiz deste repositório, você deve encontrar o arquivo
chat-schema.json
. Para importá-lo para o espaço de trabalho, você só precisa instalar a linha de comando 8base e fazer o login, e então importar o arquivo de esquema.
# 8base CLI
yarn global add 8base-cli
# CLI
8base login
#
8base import -f chat-schema.json -w <YOUR_8BASE_WORKSPACE_ID>
3. Acesso API
A tarefa final do back-end é permitir o acesso público à API GraphQL.
No console 8base, vá para
App Services > Roles > Guest
. Atualize as permissões definidas para postagens e usuários para que sejam verificadas ou definidas como Todos os registros (conforme mostrado na captura de tela abaixo).
A função de convidado determina o que o usuário que faz uma solicitação de API não autenticada tem permissão para fazer.

Editor de funções no console 8base.
4. Escrever consultas GraphQL
Nesta etapa, vamos definir e escrever todas as consultas GraphQL que precisaremos para nosso componente de bate-papo. Isso nos ajudará a entender quais dados estaremos lendo, criando e ouvindo (via WebSockets) usando a API.
O código a seguir deve ser colocado em um arquivo
src / utils / graphql.js
. Leia os comentários acima de cada constante exportada para entender o que cada consulta faz.
/* 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. Configurando o cliente Apollo para assinaturas
Com nossas consultas GraphQL escritas, é hora de configurar nossos módulos de API.
Primeiro, vamos lidar com o cliente API
ApolloClient
com seus padrões obrigatórios. Para createHttpLink
nós, fornecemos nosso terminal de espaço de trabalho totalmente formado. Este código está em 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, .
Em seguida, lidaremos com o cliente de assinatura usando
subscriptions-transport-ws
e isomorphic-ws
. Este código é um pouco mais longo que o anterior, por isso vale a pena ler os comentários no código.
Inicializamos
SubscriptionClient
usando nosso endpoint WebSockets e workspaceId
em parâmetros connectionParams
. Em seguida, usamos este subscriptionClient
em dois métodos definidos na exportação padrão: subscribe()
e close()
.
subscribe
nos permite criar novas assinaturas com dados e callbacks de erro. O método de fechamento é o que podemos usar para fechar a conexão quando sairmos do 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. Escrevendo um componente Vue
Agora temos tudo o que precisamos para criar um chat público. Resta apenas um componente para escrever
GroupChat.vue
.
Carregue o componente usando fio de saque e vamos continuar.
Nota importante: cada um tem sua própria ideia de beleza, então eu apenas criei os estilos mínimos necessários para o componente ser funcional.
Script de componente
Primeiro, precisamos importar nossos módulos, estilos simples e consultas GraphQL. Tudo isso está no nosso
src / utils
.
Declare as seguintes importações em
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";
Dados de componentes
Podemos definir quais propriedades de dados queremos usar na função de dados de nosso componente. Tudo o que precisamos é uma maneira de armazenar usuários de bate-papo, mensagens, o nome do usuário "atual" e qualquer mensagem que ainda não tenha sido enviada. Essas propriedades podem ser adicionadas da seguinte forma:
/* imports ... */
export default {
name: "GroupChat",
data: () => ({
messages: [],
newMessage: "",
me: { email: "" },
users: [],
}),
};
Ganchos de ciclo de vida
Nossos ganchos de ciclo de vida funcionam em diferentes pontos da vida de um componente Vue. Por exemplo, quando é montado ou atualizado. Neste caso, estamos interessados apenas na criação e
beforeDestroy
componente. Nesses casos, queremos abrir as inscrições de bate-papo ou fechá-las.
/* ... */
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 componente
Precisamos adicionar alguns métodos para processar cada resposta de chamada / API (
createMessage
, addMessage
, closeChat
, etc.). Todos eles serão armazenados no objeto de método de nosso componente.
É necessário
observar uma coisa: a maioria das mutações não espera e não manipula as respostas. Isso ocorre porque temos assinaturas que rastreiam essas mutações. Após um lançamento bem-sucedido, os dados do evento são processados pela assinatura.
A maioria
desses métodos fala por si. De qualquer forma, leia os comentários no código a seguir.
/* ... */
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: '' } }
}
},
/* ... */
}
Modelo de componente
Por último, mas não menos importante, temos um componente
GroupChat.vue
.
Existem
milhares de excelentes tutoriais sobre como criar belas interfaces de usuário. Este não é um deles.
O
padrão a seguir Torná-lo bonito ou não é com você. Dito isso, vamos examinar rapidamente a marcação de chave que implementamos aqui.
Como
sempre, leia os comentários embutidos no 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>
E agora o chat público está construído. Se você abri-lo em sua rede local, poderá começar a enviar e receber mensagens. Porém, para provar que se trata de um verdadeiro chat em grupo, abra várias janelas e observe o andamento da conversa.
7. Conclusão e teste
Neste tutorial, exploramos como o uso de ferramentas de desenvolvimento modernas nos permite criar aplicativos do mundo real em minutos.
Espero que você também tenha aprendido como inicializar
ApolloClient
e SubscriptionClient
executar consultas GraphQL, mutações e assinaturas de forma eficiente em um espaço de trabalho 8base, bem como um pouco sobre VueJS.
Esteja você trabalhando em um jogo móvel, mensageiros, aplicativos de notificação ou outros projetos que requerem dados em tempo real, as assinaturas são uma ótima ferramenta. E agora apenas começamos a considerá-los.
Crie um aplicativo de bate-papo com 8base
8base é um backend sem servidor pronto para uso, como um serviço criado por desenvolvedores para desenvolvedores. A plataforma 8base permite que os desenvolvedores criem aplicativos em nuvem impressionantes usando JavaScript e GraphQL. Saiba mais sobre a plataforma 8base aqui .