DEV Community

Ayus Irfang Filaras
Ayus Irfang Filaras

Posted on

Membuat realtime chat

Dalam artikel ini, kita akan membuat aplikasi Next.js dari awal dengan Prisma sebagai ORM, Socket.io untuk real-time chat, dan tanpa backend terpisah.

Semua dijalankan dalam satu proses menggunakan npm run dev.


1. Membuat Proyek Next.js

Pertama, buat proyek baru menggunakan Next.js:

npx create-next-app@latest my-app --ts --tailwind
cd my-app
Enter fullscreen mode Exit fullscreen mode

Jalankan proyek:

npm run dev
Enter fullscreen mode Exit fullscreen mode

Buka http://localhost:3000 untuk melihat tampilan default Next.js.


2. Setup Prisma di Next.js

Install Prisma dan klien database:

npm install @prisma/client @prisma/cli
npx prisma init
Enter fullscreen mode Exit fullscreen mode

Buka file prisma/schema.prisma dan ubah skema sebagai berikut:

model User {
  id    String @id @default(uuid())
  name  String
  email String @unique
}

model Message {
  id        String   @id @default(uuid())
  senderId  String
  recipientId String
  content   String
  createdAt DateTime @default(now())

  sender    User @relation(fields: [senderId], references: [id])
  recipient User @relation(fields: [recipientId], references: [id])
}
Enter fullscreen mode Exit fullscreen mode

Jalankan migrasi:

npx prisma migrate dev --name init
Enter fullscreen mode Exit fullscreen mode

Buat file /lib/prisma.ts untuk mencegah banyak instance Prisma:

import { PrismaClient } from "@prisma/client";

const globalForPrisma = global as unknown as { prisma?: PrismaClient };

export const prisma = globalForPrisma.prisma ?? new PrismaClient();

if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma;
Enter fullscreen mode Exit fullscreen mode

Buat fungsi database di /lib/messages.ts:

import { prisma } from "./prisma";

export const sendMessage = async (senderId: string, recipientId: string, content: string) => {
  return prisma.message.create({ data: { senderId, recipientId, content } });
};

export const getMessages = async (userId: string) => {
  return prisma.message.findMany({
    where: { OR: [{ senderId: userId }, { recipientId: userId }] },
    orderBy: { createdAt: "asc" },
  });
};
Enter fullscreen mode Exit fullscreen mode

3. Setup Socket.io di Next.js

Install Socket.io:

npm install socket.io socket.io-client
Enter fullscreen mode Exit fullscreen mode

Buat file /lib/socket.ts untuk menangani koneksi Socket.io:

import { Server as HttpServer } from "http";
import { Server as SocketIOServer } from "socket.io";
import { sendMessage } from "./messages";

let io: SocketIOServer | null = null;

export const initSocket = (server: HttpServer) => {
  if (!io) {
    io = new SocketIOServer(server, { cors: { origin: "*" } });

    io.on("connection", (socket) => {
      console.log("User connected:", socket.id);

      socket.on("sendMessage", async (data) => {
        const message = await sendMessage(data.senderId, data.recipientId, data.content);
        io?.emit("newMessage", message);
      });

      socket.on("disconnect", () => console.log("User disconnected:", socket.id));
    });
  }
};
Enter fullscreen mode Exit fullscreen mode

Tambahkan server.ts untuk menjalankan Next.js dan Socket.io dalam satu proses:

import { createServer } from "http";
import { initSocket } from "./lib/socket";
import next from "next";

const dev = process.env.NODE_ENV !== "production";
const app = next({ dev });
const handle = app.getRequestHandler();

app.prepare().then(() => {
  const server = createServer((req, res) => handle(req, res));

  initSocket(server);

  server.listen(3000, () => {
    console.log("Server running on http://localhost:3000");
  });
});
Enter fullscreen mode Exit fullscreen mode

Tambahkan ke package.json:

"scripts": {
  "dev": "node server.ts"
}
Enter fullscreen mode Exit fullscreen mode

4. Menggunakan Socket.io di Frontend

Buat hook /lib/useChat.ts:

import { useEffect, useState } from "react";
import { io } from "socket.io-client";

const socket = io("http://localhost:3000");

export const useChat = () => {
  const [messages, setMessages] = useState([]);

  useEffect(() => {
    socket.on("newMessage", (message) => {
      setMessages((prev) => [...prev, message]);
    });

    return () => {
      socket.off("newMessage");
    };
  }, []);

  const sendMessage = (senderId: string, recipientId: string, content: string) => {
    socket.emit("sendMessage", { senderId, recipientId, content });
  };

  return { messages, sendMessage };
};
Enter fullscreen mode Exit fullscreen mode

5. Membuat UI Chat

Di dalam components/Chat.tsx:

"use client";

import { useChat } from "@/lib/useChat";
import { useState } from "react";

export const Chat = ({ userId }: { userId: string }) => {
  const { messages, sendMessage } = useChat();
  const [content, setContent] = useState("");

  const handleSend = () => {
    sendMessage(userId, "recipient-id", content);
    setContent("");
  };

  return (
    <div className="p-4 border border-gray-300 rounded-md w-96">
      <div className="h-60 overflow-y-auto border-b border-gray-300 mb-2 p-2">
        {messages.map((msg, index) => (
          <div key={index} className="p-2 bg-gray-100 rounded-md my-1">
            {msg.content}
          </div>
        ))}
      </div>
      <div className="flex gap-2">
        <input
          className="flex-1 p-2 border rounded-md"
          value={content}
          onChange={(e) => setContent(e.target.value)}
        />
        <button className="bg-blue-500 text-white px-4 py-2 rounded-md" onClick={handleSend}>
          Send
        </button>
      </div>
    </div>
  );
};
Enter fullscreen mode Exit fullscreen mode

Kesimpulan

Dengan pendekatan ini:

  • Next.js digunakan sebagai frontend dan backend dalam satu proses.
  • Prisma dikelola langsung tanpa API Routes.
  • Socket.io berjalan dalam server Next.js.
  • Chat real-time bisa langsung digunakan dengan npm run dev.

Pendekatan ini sangat cocok untuk proyek sederhana tanpa backend terpisah.

Hostinger image

Get n8n VPS hosting 3x cheaper than a cloud solution

Get fast, easy, secure n8n VPS hosting from $4.99/mo at Hostinger. Automate any workflow using a pre-installed n8n application and no-code customization.

Start now

Top comments (0)

Image of Datadog

The Essential Toolkit for Front-end Developers

Take a user-centric approach to front-end monitoring that evolves alongside increasingly complex frameworks and single-page applications.

Get The Kit

👋 Kindness is contagious

If this article connected with you, consider tapping ❤️ or leaving a brief comment to share your thoughts!

Okay