Как стать автором
Обновить

Создание бэкенд приложения для онлайн чата Apollo, Node.js

Время на прочтение3 мин
Количество просмотров7.9K
Некоторое время назад я работал над мобильным приложением, функционал которого включал в себя удобный онлайн-чат. И теперь я решил написать статью с краткой инструкцией, как создать чат, используя apollo server и node.js на бэкенде, а так же react native и apollo client на клиентской части.

Статья разбита на две части для удобства прочтения. В первой части содержится гайд по созданию бэкенд приложения, а во второй — гайд по созданию фронтенд приложения.

Если вам лень читать, можно сразу посмотреть код в Github’e здесь и здесь.

В качестве основных технологий для реализации я выбрал node.js фреймворк koa, базу данных postgresql, а так же GraphQL сервер — apollo-server-koa.

Первым делом, был сгенерирован пустой koa2 проект, для этого я использовал простой koa-generator, выполнив в терминале команду: 

$ koa <project name>

Далее были установлены необходимые зависимости, я делаю это с помощью yarn, но вы можете воспользоваться npm.

$ yarn add apollo-server-koa knex objection pg

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


Для подключения к БД нужно описать два файла, первый из них — db.js, который будет экспортировать инстанс клиента knex и позволит нашим моделям работать с даннными из базы, второй — knexfile.js, который содержит в себе настройки подключения к БД для создания и накатывания миграций.

Код db.js описан ниже, обратите внимание, что все настройки берутся из переменных окружения:

const db = require('knex')({
 client: 'pg',
 connection: {
   host : process.env.POSTGRES_HOST,
   port: process.env.POSTGRES_PORT,
   user : process.env.POSTGRES_USER,
   password : process.env.POSTGRES_PASSWORD,
   database : process.env.POSTGRES_DATABASE
 }
});

module.exports = db;

Код knexfile.js доступен по ссылке.

Теперь можно описать миграции для создания двух необходимых нам таблиц


Сами таблицы будут максимально просты и содержать лишь минимальный необходимый набор полей. Команда для их создания ниже:

$ knex migrate:make migration_name

Посмотреть файлы миграций можно по ссылке.

Теперь создадим модели сущностей Message и User


class Message extends Model {
 static get tableName() {
   return 'messages';
 }

 $beforeInsert() {
   this.created_at = new Date().toISOString();
 }

 static get relationMappings() {
   return {
     user: {
       relation: Model.BelongsToOneRelation,
       modelClass: User,
       join: {
         from: 'messages.user_id',
         to: 'users.id'
       }
     }
   };
 }
}

Осталось самое интересное — подключение и настройка apollo-server-koa, описание graphql схемы и резолверов.

Для подключения apollo-server-koa достаточно добавить следующие строки кода


app.js:

const { ApolloServer } = require('apollo-server-koa');
const graphqlSchema = require('./graphqlSchema');
…
const apolloServer = new ApolloServer(graphqlSchema);

apolloServer.applyMiddleware({ app });

www:

var { app, apolloServer } = require('../app');
...
apolloServer.installSubscriptionHandlers(server);

Помимо подключения apollo-server-koa, мы включили возможность работы с подписками для оповещения клиентов о том, что в чате пришло новое сообщение.

Apollo-server-koa подключен, следующий шаг — описание graphql-схемы с необходимыми для чата типами


input UserInput {
 username: String!
}
input MessageInput {
 text: String!
 user_id: ID!
}
type User {
 id: ID
 username: String
}
type Message {
 id: ID
 text: String
 created_at: String
 user: User
}
type Query {
 getLast100Messages: [Message]
}
type Mutation {
 findOrCreateUser(user: UserInput!): User
 createMessage(message: MessageInput!): Message
}
type Subscription {
 messageCreated: Message
}

Схема готова, опишем резолверы


Пример резолвера для отправки нового сообщения:

const Message = require('../../models/message');
const { pubsub, MESSAGE_CREATED } = require('../../utils');

module.exports = {
 createMessage: async (obj, { message }, context, info) => {
   const createdMessage = await Message
     .query()
     .insert(message);

   const resultMessage = await Message
     .query()
     .eager('user')
     .findById(createdMessage.id);
   pubsub.publish(MESSAGE_CREATED, { messageCreated: resultMessage });
   return resultMessage;
 },
};

Интересный момент — помимо сохранения сообщения в БД, здесь вызывается функция publish() которая оповещает всех подписчиков о событии MESSAGE_CREATED, отправляя им объект нового сообщения (внимательный читатель заметит, что отправитель тоже будет оповещен о своем же новом сообщении, и мы обработаем это далее на клиенте, в реальном же проекте имеет смысл обработать это на стороне бекенда, чтобы не дублировать логику среди различных клиентов).

С кодом оставшихся резволеров можно ознакомиться по ссылке.

Серверная часть чата готова, как проверить, что все работает?


Откройте хост в своем браузере и в нем вы увидите graphql playground.

image

В следующей части мы займемся созданием мобильного приложения.
Теги:
Хабы:
+9
Комментарии2

Публикации

Изменить настройки темы

Истории

Работа

Ближайшие события

Weekend Offer в AliExpress
Дата20 – 21 апреля
Время10:00 – 20:00
Место
Онлайн
Конференция «Я.Железо»
Дата18 мая
Время14:00 – 23:59
Место
МоскваОнлайн