0
0

Node.js、Express、GraphQL、htmxを使ったチャットアプリの作成

Posted at

このアプリについて

このチュートリアルでは、Node.jsとExpressをバックエンドに、GraphQLをデータ取得に、htmxをフロントエンドに使用したリアルタイムチャットアプリを作成します。

また、他のユーザーがチャットに参加しているかどうか、メッセージを読んだかどうかも確認できる機能を追加します。

必要なツール

  • Node.js
  • npm
  • Express
  • Apollo Server (GraphQL)
  • htmx

各技術の説明

Node.js: JavaScriptランタイムで、サーバーサイドのスクリプトを実行するために使用されます。

Express: Node.js上で動作するウェブアプリケーションフレームワークで、APIの作成やルーティングに便利です。

GraphQL: データの取得と操作を行うためのクエリ言語で、クライアントが必要なデータだけを取得できます。

htmx: HTML属性を使って、サーバーからのデータを直接DOMに反映させることができるライブラリです。

プロジェクトのセットアップ

Node.jsとExpressのインストール

mkdir chat-app
cd chat-app
npm init -y
npm install express apollo-server-express graphql htmx

サーバーの設定

server.jsを作成し、ExpressとApollo Serverを設定します。

const express = require('express');
const { ApolloServer, gql, PubSub } = require('apollo-server-express');
const bodyParser = require('body-parser');

const app = express();
app.use(bodyParser.json());

const pubsub = new PubSub();
const MESSAGE_ADDED = 'MESSAGE_ADDED';

const typeDefs = gql`
  type Message {
    id: ID!
    content: String!
    user: String!
    readBy: [String!]
  }
  type Query {
    messages: [Message]
  }
  type Mutation {
    addMessage(content: String!, user: String!): Message
    markAsRead(messageId: ID!, user: String!): Message
  }
  type Subscription {
    messageAdded: Message
  }
`;

let messages = [];

const resolvers = {
  Query: {
    messages: () => messages,
  },
  Mutation: {
    addMessage: (_, { content, user }) => {
      const message = { id: messages.length + 1, content, user, readBy: [] };
      messages.push(message);
      pubsub.publish(MESSAGE_ADDED, { messageAdded: message });
      return message;
    },
    markAsRead: (_, { messageId, user }) => {
      const message = messages.find(msg => msg.id == messageId);
      if (message && !message.readBy.includes(user)) {
        message.readBy.push(user);
      }
      return message;
    }
  },
  Subscription: {
    messageAdded: {
      subscribe: () => pubsub.asyncIterator([MESSAGE_ADDED])
    }
  }
};

const server = new ApolloServer({ typeDefs, resolvers });
server.applyMiddleware({ app });

app.listen({ port: 4000 }, () =>
  console.log(`Server ready at http://localhost:4000${server.graphqlPath}`)
);

フロントエンドの設定

index.htmlを作成し、htmxを使用してチャットインターフェースを構築します。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>チャットアプリ</title>
  <script src="https://unpkg.com/htmx.org@1.9.10"></script>
  <script src="https://unpkg.com/htmx.org/dist/ext/ws.js"></script>
</head>
<body>
  <div id="chat">
    <div hx-get="/messages" hx-trigger="load" hx-swap="innerHTML"></div>
    <form hx-post="/addMessage" hx-trigger="submit" hx-swap="beforeend">
      <input type="text" name="content" required>
      <input type="hidden" name="user" value="ユーザー名">
      <button type="submit">送信</button>
    </form>
  </div>
  <div id="read-status">
    <div hx-get="/readStatus" hx-trigger="load" hx-swap="innerHTML"></div>
  </div>
</body>
</html>

メッセージの取得と追加

サーバー側でメッセージの取得と追加をハンドリングするエンドポイントを設定します。

app.get('/messages', (req, res) => {
  res.send(messages.map(msg => `<div>${msg.user}: ${msg.content}</div>`).join(''));
});

app.post('/addMessage', (req, res) => {
  const { content, user } = req.body;
  const message = { id: messages.length + 1, content, user, readBy: [] };
  messages.push(message);
  res.send(`<div>${user}: ${content}</div>`);
});

メッセージの既読状態の管理

メッセージが読まれたかどうかを管理するためのエンドポイントを追加します。

app.post('/markAsRead', (req, res) => {
  const { messageId, user } = req.body;
  const message = messages.find(msg => msg.id == messageId);
  if (message && !message.readBy.includes(user)) {
    message.readBy.push(user);
  }
  res.send(message);
});

app.get('/readStatus', (req, res) => {
  res.send(messages.map(msg => `<div>${msg.user}: ${msg.content} - Read by: ${msg.readBy.join(', ')}</div>`).join(''));
});

まとめ

このチュートリアルでは、Node.jsとExpressをバックエンドに、GraphQLをデータ取得に、htmxをフロントエンドに使用したチャットアプリを作成しました。

また、他のユーザーがチャットに参加しているかどうか、メッセージを読んだかどうかも確認できる機能を追加しました。

詳細なコードと設定により、リアルタイムでメッセージを送受信できるシンプルなチャットアプリを構築しました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0