Русский
Русский
English
Статистика
Реклама

Перевод Как создать приложение-чат за двадцать минут

image

Мой отец любит напоминать мне, что, будучи компьютерным инженером в 1970-х, он был программистом до того, как программирование стало модным. Пару раз он даже показывал старые скрипты Fortran и COBOL. Прочитав этот код, я с уверенностью могу сказать, что программирование сегодня определенно круче.

Отличительная черта современных языков программирования и сред разработки это то, насколько меньше кода приходится писать разработчику. Используя высокоуровневые языки вместе со множеством доступных API-интерфейсов, пакетов с открытым исходным кодом и платных сервисов, приложения даже со сложными требованиями можно создавать довольно быстро.

Сравнением, позволяющим продемонстрировать эволюцию разработки программного обеспечения, является строительство. Когда-то строительство любого дома начиналось с вырубки деревьев на вашем участке. Однако быстро появились материалы, инструменты и способы, чтобы строительство завершалось быстрее, объекты становились прочнее, а рабочие освобождались от некоторых элементарных задач.

Сколько было бы построено небоскребов, если бы строители сами добывали себе сталь?

Разработчики ПО, которые продолжают работать и по сей день, на заре карьеры сами рубили себе деревья. При этом беспрецедентные инновации последнего десятилетия привели к тому, что индустрия программного обеспечения стала развиваться примерно так же, как и строительство.

Проще говоря, у современных разработчиков теперь есть инструменты, техника и передовые методы, которые позволяют быстрее завершать проекты, получать стабильные приложения, а так же избавляют разработчиков от задач низкого уровня.

Как сделать приложение для чата


Давайте быстро создадим что-нибудь, что раньше занимало бы дни или недели. Мы сделаем Public Chat Room приложение, которое использует WebSockets для обмена сообщениями в реальном времени.

WebSockets нативно поддерживаются всеми современными браузерами. Однако наша цель выяснить, какие инструменты мы можем использовать в работе, а не изобретать их. Учитывая это, мы будем использовать следующие технологии:

  • 8base управляемый GraphQL API
  • VueJS JavaScript фреймворк

Стартовый проект и полный файл README можно найти в этом репозитории GitHub. Если вы хотите просмотреть только готовое приложение, загляните в ветку public-chat-room.

Кроме того, в видео ниже (на английском языке) более подробно объясняется каждый шаг.

Начнем.

Семь шагов для создания чат приложения:


1. Настройка проекта


Клонируйте стартовый проект и перейдите в директорию группового чата. Вы можете сами определить, использовать yarn или npm для установки зависимостей проекта. В любом случае, нам нужны все NPM пакеты, обозначенные в файле package.json.

# Клонируем проектgit clone https://github.com/8base/Chat-application-using-GraphQL-Subscriptions-and-Vue.git group-chat# Переходим в директориюcd group-chat# Устанавливаем зависимостиyarn

Чтобы взаимодействовать с GraphQL API, мы должны настроить три переменные среды. Создайте файл .env.local в корневой директории с помощью следующей команды, и приложение Vue после инициализации автоматически установит переменные среды, которые мы добавили в этот файл.

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.

Если у вас есть воркспейс 8base, который вы хотите использовать для создания чат-приложения по нашему руководству, обновите файл .env.local, указав свой идентификатор воркспейса. Если нет получите идентификатор воркспейса, выполнив шаги 1 и 2 из 8base Quickstart.

2. Импорт схемы


Теперь нам нужно подготовить серверную часть. В корне этого репозитория вы должны найти файл chat-schema.json. Чтобы импортировать его в рабочую область, нужно просто установить командную строку 8base и залогиниться, а затем импортировать файл схемы.

# Установка 8base CLIyarn global add 8base-cli# Аутентификация CLI8base login# Импортируем схему в нашу рабочую область8base import -f chat-schema.json -w <YOUR_8BASE_WORKSPACE_ID>

3. Доступ к API


Последняя задача по бэкенду разрешить публичный доступ к GraphQL API.

В консоли 8base перейдите в App Services > Roles > Guest. Обновите разрешения, установленные как для сообщений, так и для пользователей, чтобы они были или отмечены галочкой, или установлены как All Records (как показано на скриншоте ниже).

Роль Guest определяет, что разрешено делать пользователю, отправившему неаутентифицированный запрос к API.

image
Редактор ролей в консоли 8base.

4. Пишем GraphQL запросы


На этом этапе мы собираемся определить и выписать все запросы GraphQL, которые нам понадобятся для нашего компонента чата. Это поможет нам понять, какие данные мы будем читать, создавать и прослушивать (через WebSockets) с помощью API.

Следующий код следует поместить в файл src / utils / graphql.js. Прочтите комментарии над каждой экспортированной константой, чтобы понять, что выполняет каждый запрос.

/* 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. Настройка Apollo клиента для подписок


Когда наши запросы GraphQL написаны, самое время настроить наши модули API.

Во-первых, давайте займемся клиентом API с помощью ApolloClient с его обязательными настройками по умолчанию. Для createHttpLink мы предоставляем наш полностью сформированный эндпоинт воркспейса. Этот код находится в 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, обратитесь к их документации.

Затем займемся клиентом подписки, используя subscriptions-transport-ws и isomorphic-ws. Этот код немного длиннее, чем предыдущий, поэтому стоит потратить время на чтение комментариев в коде.

Мы инициализируем SubscriptionClient, используя наш эндопоинт WebSockets и workspaceId в параметрах connectionParams. Затем мы используем этот subscriptionClient в двух методах, определенных в экспорте по умолчанию: subscribe() и close().

subscribe позволяет нам создавать новые подписки с обратными вызовами данных и ошибок. Метод close это то, что мы можем использовать, чтобы закрыть соединение при выходе из чата.

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. Написание компонента Vue


Теперь у нас есть все необходимое для создания публичного чата. Осталось только написать один компонент GroupChat.vue.

Загрузите компонент с помощью yarn serve, и продолжим.

Важное замечание: у каждого свое представление о красоте, поэтому я сделал только минимальные стили, необходимые для того, чтобы компонент был функциональным.

Скрипт компонента


Сначала нам нужно импортировать наши модули, простые стили и GraphQL запросы. Всё это находится в нашем каталоге src / utils.
Объявите следующие импорты в 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";

Компонентные данные


Мы можем определить, какие свойства данных мы хотим использовать в функции data нашего компонента. Все, что нам нужно, это способ хранить пользователей чата, сообщения, имя текущего пользователя и любое сообщение, которое еще не было отправлено. Эти свойства можно добавить следующим образом:

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

Хуки жизненного цикла


Наши хуки жизненного цикла выполняются в разные моменты жизни компонента Vue. Например, когда он монтируется или обновляется. В данном случае нас интересует только создание и beforeDestroy компонента. В таких случаях мы хотим либо открыть подписки на чат, либо закрыть.

/* ипорты... */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();},};

Методы компонента


Мы должны добавить определенные методы, предназначенные для обработки каждого вызова / ответа API (createMessage, addMessage, closeChat, и т.д.). Все они будут сохранены в объекте методов нашего компонента.

Следует отметить одну вещь: большинство мутаций не ждут и не обрабатывают ответы. Это происходит потому, что у нас работают подписки, которые отслеживают эти мутации. После успешного запуска данные о событиях обрабатываются именно подпиской.

Большинство этих методов говорят сами за себя. В любом случае, прочтите комментарии в следующем коде.

/* импорты ... */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: '' } }  }},/* Хуки ... */}

Шаблон компонента


И последнее, но не менее важное: у нас есть компонент GroupChat.vue.

Есть тысячи отличных руководств о том, как создавать красивые пользовательские интерфейсы. Это не одно из них.

Следующий шаблон соответствует минимальным требованиям для чат-приложения. Делать его красивым или нет это уже ваше дело. Тем не менее, давайте быстро пройдемся по ключевой разметке, которую мы здесь реализовали.

Как всегда, читайте встроенные комментарии к коду.

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

И вот публичный чат построен. Если вы откроете его в своей локальной сети, вы сможете начать отправлять и получать сообщения. Однако, чтобы доказать, что это настоящий групповой чат, откройте несколько окон и наблюдайте за ходом разговора.

7. Заключение и тестирование


В этом руководстве мы изучили, как использование современных инструментов разработки позволяет нам создавать реальные приложения за считанные минуты.

Надеюсь, вы также узнали, как инициализировать ApolloClient и SubscriptionClient для эффективного выполнения запросов GraphQL, мутаций и подписок в воркспейсе 8base, а также немного о VueJS.

Независимо от того, работаете ли вы над мобильной игрой, мессенджерами, приложениями-уведомлениями, или над другими проектами, требующими данных в реальном времени, подписки отличный инструмент. И сейчас мы только начали их рассматривать.

Создайте чат-приложение с 8base


8base это готовый к работе бессерверный бэкенд-как-сервис, созданный разработчиками для разработчиков. Платформа 8base позволяет разработчикам создавать потрясающие облачные приложения с использованием JavaScript и GraphQL. Узнайте больше о платформе 8base здесь.
Источник: habr.com
К списку статей
Опубликовано: 09.11.2020 12:16:47
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Мессенджеры

Javascript

Программирование

Vuejs

Graphql

Chat

Vue

Websocket

8base

Api

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru