Panduan Lengkap Setup Next.js 14 dengan App Router, Server Actions, dan Typescript


Next.js 14 hadir dengan fitur App Router yang revolusioner serta Server Actions untuk mengoptimalkan performa. Ikuti tutorial step‑by‑step ini untuk membangun aplikasi full‑stack modern menggunakan Typescript, Docker, dan best practice keamanan.

1. Persiapan Lingkungan

Pastikan Anda memiliki Node.js 20.x atau lebih baru, npm 10 (atau yarn 4), serta Docker Desktop terinstal. Verifikasi dengan:

node -v
npm -v
docker --version

1.1. Membuat Direktori Proyek

mkdir nextjs14-app && cd nextjs14-app

1.2. Inisialisasi Project dengan Create‑Next‑App

npx create-next-app@latest . \
  --ts \
  --app \
  --eslint \
  --src-dir \
  --import-alias "@/*"

Opsi --app mengaktifkan App Router secara default.

2. Struktur Direktori Baru (src)

src/
├─ app/                # App Router (pages) 
│  ├─ layout.tsx      # Root layout
│  ├─ page.tsx        # Home page
│  └─ (dashboard)/    # Nested route contoh
│     ├─ layout.tsx
│     └─ page.tsx
├─ components/        # Komponen UI reusable
├─ lib/                # Helper, API client
├─ public/            # Asset statis
└─ styles/            # CSS/SCSS

3. Instalasi Dependency Tambahan

npm i prisma @prisma/client \
  next-auth \
  tailwindcss postcss autoprefixer \
  class-variance-authority clsx \
  zod
npx tailwindcss init -p

Konfigurasi tailwind.config.js untuk mode JIT dan path ke src/app:

module.exports = {
  content: ["./src/**/*.{js,ts,jsx,tsx}"] ,
  theme: { extend: {} },
  plugins: [],
};

4. Setup Database dengan Prisma

4.1. Inisialisasi Prisma

npx prisma init --datasource-provider postgresql

Edit .env:

DATABASE_URL="postgresql://postgres:password@localhost:5432/next14db?schema=public"

4.2. Definisikan Model

model User {
  id        String   @id @default(cuid())
  email     String   @unique
  name      String?
  password  String   // hashed via bcrypt
  createdAt DateTime @default(now())
}

4.3. Migrasi

npx prisma migrate dev --name init

5. Implementasi Server Actions (Next.js 14)

Server Actions memungkinkan Anda menulis fungsi async di server yang dipanggil langsung dari komponen client.

5.1. Buat Action untuk Registrasi

/* src/app/(auth)/register/action.ts */
"use server";
import { prisma } from "@/lib/prisma";
import { hash } from "bcryptjs";
import { redirect } from "next/navigation";
import { z } from "zod";

const schema = z.object({
  email: z.string().email(),
  name: z.string().min(2),
  password: z.string().min(8),
});

export async function registerAction(formData: FormData) {
  const result = schema.safeParse({
    email: formData.get("email"),
    name: formData.get("name"),
    password: formData.get("password"),
  });
  if (!result.success) throw new Error("Invalid input");
  const { email, name, password } = result.data;
  const hashed = await hash(password, 12);
  await prisma.user.create({ data: { email, name, password: hashed } });
  redirect("/login");
}

5.2. Konsumsi Action di Komponen Client

/* src/app/(auth)/register/page.tsx */
"use client";
import { registerAction } from "./action";

export default function RegisterPage() {
  return (
    
); }

6. Konfigurasi Authentication dengan Next‑Auth

6.1. Buat API Route

/* src/app/api/auth/[...nextauth]/route.ts */
import NextAuth from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
import { prisma } from "@/lib/prisma";
import { compare } from "bcryptjs";

export const authOptions = {
  providers: [
    CredentialsProvider({
      name: "Credentials",
      credentials: { email: { label: "Email", type: "text" }, password: { label: "Password", type: "password" } },
      async authorize(credentials) {
        const user = await prisma.user.findUnique({ where: { email: credentials?.email } });
        if (user && (await compare(credentials!.password, user.password))) {
          return { id: user.id, email: user.email, name: user.name };
        }
        return null;
      },
    }),
  ],
  session: { strategy: "jwt" },
  secret: process.env.NEXTAUTH_SECRET,
};

export const GET = async (req: Request) => NextAuth(req, authOptions);
export const POST = async (req: Request) => NextAuth(req, authOptions);

6.2. Proteksi Route Dashboard

/* src/app/(dashboard)/layout.tsx */
import { auth } from "@/lib/auth";
import { redirect } from "next/navigation";

export default async function DashboardLayout({ children }: { children: React.ReactNode }) {
  const session = await auth();
  if (!session) redirect("/login");
  return (
{children}
); }

7. Dockerisasi Aplikasi

7.1. Dockerfile

# syntax=docker/dockerfile:1
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json .
RUN npm ci
COPY . .
RUN npm run build

FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY --from=builder /app/.next ./.next
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/public ./public
COPY --from=builder /app/package*.json ./
EXPOSE 3000
CMD ["npm", "start"]

7.2. docker-compose.yml

version: "3.9"
services:
  web:
    build: .
    ports:
      - "3000:3000"
    environment:
      - DATABASE_URL=postgresql://postgres:password@db:5432/next14db?schema=public
      - NEXTAUTH_SECRET=${NEXTAUTH_SECRET}
    depends_on:
      - db
  db:
    image: postgis/postgis:15-3.4
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: password
      POSTGRES_DB: next14db
    volumes:
      - pgdata:/var/lib/postgresql/data
volumes:
  pgdata:

8. Best Practice & Security

  • Environment Variables: Gunakan .env.local untuk dev dan secret manager (AWS SSM, GCP Secret Manager) di prod.
  • Input Validation: Selalu validasi dengan zod atau yup di server actions.
  • Rate Limiting: Tambahkan middleware next-rate-limit pada API routes untuk mencegah brute‑force.
  • HTTP Headers: Pakai helmet via custom server atau next-secure-headers untuk CSP, HSTS, dll.
  • CSRF Protection: Next‑Auth sudah melindungi token, tapi untuk action custom gunakan csrf token di form.
  • Logging & Monitoring: Integrasikan dengan pino dan Grafana Loki lewat sidecar Docker.

9. Deployment ke Vercel (Opsional)

  1. Push repository ke GitHub.
  2. Di Vercel, pilih Import Project, sambungkan repository.
  3. Set environment variables: DATABASE_URL, NEXTAUTH_SECRET.
  4. Vercel otomatis mengenali next.config.js dan melakukan build.

10. Testing Dasar

npm i -D jest @testing-library/react @testing-library/jest-dom ts-jest
npx jest --init

Contoh test komponen RegisterPage:

import { render, screen } from "@testing-library/react";
import RegisterPage from "@/app/(auth)/register/page";

test("renders registration form", () => {
  render();
  expect(screen.getByPlaceholderText(/email/i)).toBeInTheDocument();
  expect(screen.getByPlaceholderText(/password/i)).toBeInTheDocument();
});

Dengan mengikuti tutorial ini Anda memiliki aplikasi Next.js 14 yang sepenuhnya modern: App Router, Server Actions, TypeScript, Prisma ORM, autentikasi berbasis credential, serta Docker untuk lingkungan produksi yang konsisten. Terapkan best practice keamanan, testing, dan CI/CD untuk menjamin kualitas kode. Selamat mengembangkan!
Panduan lengkap setup Next.js 14 dengan App Router, Server Actions, Typescript, Prisma, Docker, serta best practice keamanan dan deployment.

Programming,Software Engineering,Web Development

#Programming #SoftwareEngineering #WebDev #Tech #Coding

Posting Komentar

0 Komentar