Membuat Aplikasi Next.js dengan Prisma dan Socket.io

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

1. Membuat Proyek Next.js

Jalankan perintah berikut untuk membuat proyek baru:

npx create-next-app@latest my-app --ts --tailwind

Kemudian masuk ke folder proyek dan jalankan:

npm run dev

2. Setup Prisma di Next.js

Instal Prisma dan klien database:

npm install @prisma/client @prisma/cli

Inisialisasi Prisma:

npx prisma init

Skema Prisma

<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])
}

Jalankan migrasi:

npx prisma migrate dev --name init

3. Setup Socket.io di Next.js

Instal Socket.io:

npm install socket.io socket.io-client

Konfigurasi Socket.io

Buat file /lib/socket.ts:

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));
    });
  }
};

4. Menjalankan Server Next.js dan Socket.io dalam Satu Proses

Buat file server.ts:

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");
  });
});

Ubah skrip package.json:

"scripts": {
  "dev": "node server.ts"
}

5. Membuat UI Chat

Buat komponen 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>
  );
};

Kesimpulan

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

Dengan pendekatan ini, aplikasi sederhana bisa dibuat lebih efisien tanpa perlu backend terpisah.