แสดงบทความที่มีป้ายกำกับ Middleware แสดงบทความทั้งหมด
แสดงบทความที่มีป้ายกำกับ Middleware แสดงบทความทั้งหมด

วันอังคารที่ 25 มีนาคม พ.ศ. 2568

วิธีป้องกันหน้าเว็บที่ต้องล็อกอินก่อนเข้าใช้งานใน Next.js

อย่าปล่อยให้ใครเข้ามาเที่ยวเว็บเราฟรีๆ! 😆

ถ้าคุณทำเว็บที่มีหน้า Dashboard, Profile หรือหน้าข้อมูลสำคัญ คุณคงไม่อยากให้ใครก็ได้เข้าถึงข้อมูลพวกนั้นได้ง่ายๆ เราต้องล็อกอินก่อนถึงจะเข้าได้!

ในบทความนี้ เราจะมาดูกันว่า Next.js + NextAuth.js ใช้ทำ Protected Route (หน้าที่ต้องล็อกอินก่อนเข้า) ได้ยังไง

🚀 ทำไมต้องป้องกันหน้าเว็บ?

✅ ป้องกันข้อมูลสำคัญ

  • ถ้าเว็บมีข้อมูลผู้ใช้ ห้ามให้คนที่ไม่ได้ล็อกอินเข้าถึง

✅ เพิ่มความปลอดภัย

  • ไม่เปิดช่องให้ Bot หรือ Hacker แอบเข้ามาดูข้อมูล

✅ UX ดีขึ้น

  •     ถ้าไม่ได้ล็อกอิน 👉 Redirect ไปหน้า Login
  •     ล็อกอินแล้ว 👉 เข้าใช้งานได้ปกติ

สรุป: ทำให้เว็บ ปลอดภัย + เป็นระเบียบ + ใช้งานง่าย


🔥 วิธีทำ Protected Route ใน Next.js

1️⃣ ติดตั้ง NextAuth.js

ถ้ายังไม่มี NextAuth.js ให้ติดตั้งก่อน

npm install next-auth

2️⃣ ตั้งค่า NextAuth.js

สร้างไฟล์ pages/api/auth/[...nextauth].js

import NextAuth from "next-auth";
import GoogleProvider from "next-auth/providers/google";

export default NextAuth({
  providers: [
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET,
    }),
  ],
  secret: process.env.NEXTAUTH_SECRET,
});

💡 Tip: เราใช้ Google Login แต่คุณเปลี่ยนไปใช้ Auth0, GitHub, หรือ Email/Password ได้

3️⃣ ตั้งค่า ENV

สร้างไฟล์ .env.local แล้วใส่ค่า

GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
NEXTAUTH_SECRET=your-random-secret
NEXTAUTH_URL=http://localhost:3000


🛑 ป้องกันหน้าที่ต้องล็อกอิน

❌ วิธีที่ 1: เช็กใน Component

import { useSession, signIn } from "next-auth/react";

export default function Dashboard() {
  const { data: session, status } = useSession();

  if (status === "loading") return <p>Loading...</p>;
  if (!session) return <button onClick={() => signIn()}>Login to access</button>;

  return <h1>Welcome to your Dashboard, {session.user.name}!</h1>;
}

🔹 อธิบายโค้ด:
  •     ถ้ากำลังโหลด ให้แสดง Loading
  •     ถ้าไม่ได้ล็อกอิน ให้แสดงปุ่ม Login
  •     ถ้าล็อกอินแล้ว แสดงข้อมูลได้ปกติ

🚀 วิธีที่ 2: Redirect ไปหน้า Login อัตโนมัติ

ใช้ getServerSideProps เช็กสิทธิ์ก่อนโหลดหน้า

import { getSession } from "next-auth/react";

export async function getServerSideProps(context) {
  const session = await getSession(context);

  if (!session) {
    return {
      redirect: {
        destination: "/login",
        permanent: false,
      },
    };
  }

  return {
    props: { session },
  };
}

export default function Dashboard({ session }) {
  return <h1>Welcome, {session.user.name}!</h1>;
}

🔹 อธิบายโค้ด:
  •     ถ้า ไม่ได้ล็อกอิน 👉 Redirect ไป /login
  •     ถ้า ล็อกอินแล้ว 👉 ให้เข้า Dashboard ได้

✅ ข้อดี:
  •     ป้องกันตั้งแต่ฝั่งเซิร์ฟเวอร์
  •     SEO Friendly เพราะไม่ได้บล็อกการโหลดหน้า

🔒 วิธีที่ 3: สร้าง Middleware ป้องกันทุกหน้า

ใช้ middleware.ts เพื่อบังคับให้ล็อกอินทุกครั้งที่เข้า /dashboard

สร้างไฟล์ middleware.ts

import { NextRequest, NextResponse } from "next/server";

export function middleware(req: NextRequest) {
  const token = req.cookies.get("next-auth.session-token");

  if (!token) {
    return NextResponse.redirect(new URL("/login", req.url));
  }

  return NextResponse.next();
}

export const config = {
  matcher: "/dashboard/:path*",
};

🔹 อธิบายโค้ด:
  •     ถ้าไม่มี Token 👉 Redirect ไป /login
  •     ถ้ามี Token 👉 อนุญาตให้เข้า /dashboard ได้

✅ ข้อดี:
  •     ป้องกันทุกหน้าใน /dashboard/ อัตโนมัติ
  •     ไม่ต้องใส่โค้ดป้องกันทุกไฟล์

🎨 สร้างหน้า Login

สร้าง pages/login.js

import { signIn } from "next-auth/react";

export default function Login() {
  return (
    <div>
      <h1>Login</h1>
      <button onClick={() => signIn("google")}>Login with Google</button>
    </div>
  );
}

🔹 อธิบายโค้ด:
  •     ปุ่มเดียวจบ! กดแล้วล็อกอินผ่าน Google


❓ คำถามที่พบบ่อย

1️⃣ ควรใช้วิธีไหนดีที่สุด?

ขึ้นอยู่กับโปรเจ็กต์:
  •     หน้าเดียวกัน (Client-side protection) 👉 useSession()
  •     ป้องกันทุกหน้า (Server-side protection) 👉 getServerSideProps()
  •     ป้องกันโฟลเดอร์ (Global protection) 👉 middleware.ts

2️⃣ NextAuth.js รองรับอะไรบ้าง?

  •     Google, Facebook, GitHub, Apple, Twitter
  •     Email/Password
  •     Magic Link

3️⃣ ถ้าอยากให้บางหน้าล็อกอิน แต่บางหน้าไม่ต้องทำไง?

  •     ใช้ Middleware เฉพาะโฟลเดอร์
  •     เช็ก useSession() ใน Component

🎉 สรุป

  •     ป้องกันหน้าเว็บที่ต้องล็อกอินก่อนเข้าใช้งาน ได้หลายวิธี
  •     ใช้ useSession() ถ้าต้องการป้องกันจากฝั่ง Client
  •     ใช้ getServerSideProps() ถ้าต้องการ Redirect อัตโนมัติ
  •     ใช้ middleware.ts ถ้าต้องการป้องกันทั้งโฟลเดอร์
ลองทำดู แล้วจะติดใจ! 😉

วันเสาร์ที่ 22 มีนาคม พ.ศ. 2568

การทำ Role-based Authentication ใน Next.js – แยกสิทธิ์ Admin, User, และ Guest

อยากให้เว็บ Next.js ของเรามีระบบแบ่งสิทธิ์การเข้าถึง (RBAC – Role-Based Access Control) ไหม?
เช่น Admin ดูข้อมูลทั้งหมดได้, User ใช้งานปกติ, Guest เข้าได้เฉพาะบางหน้า

🎯 วันนี้เราจะมาทำ Role-based Authentication ใน Next.js

✅ รองรับ JWT Authentication
✅ ใช้ Middleware เช็ก Role ก่อนเข้าหน้าเว็บ
✅ มีตัวอย่าง API แยกสิทธิ์ Admin และ User

🎯 Role-based Authentication คืออะไร?

RBAC (Role-Based Access Control) คือ การกำหนดสิทธิ์ของผู้ใช้ตามบทบาท (Role) เช่น

  • Admin 🛡️ – แก้ไขข้อมูลทุกอย่างได้
  • User 👤 – ใช้งานฟีเจอร์ปกติ
  • Guest 👥 – ดูข้อมูลบางอย่างได้

💡 เราจะใช้ JWT (JSON Web Token) ในการจัดการ Authentication & Role


🚀 1. ติดตั้งโปรเจกต์ Next.js และไลบรารี

เริ่มต้นด้วยการสร้างโปรเจกต์ Next.js และติดตั้งไลบรารีที่จำเป็น

npx create-next-app role-based-auth
cd role-based-auth
npm install jsonwebtoken bcryptjs cookie

  • jsonwebtoken – ใช้สำหรับสร้างและตรวจสอบ JWT
  • bcryptjs – ใช้เข้ารหัสรหัสผ่าน
  • cookie – ใช้จัดการ Token ผ่าน Cookie


🔐 2. สร้างระบบ Authentication (JWT)

📌 สร้าง API Register (สมัครสมาชิก)

📌 ไฟล์: pages/api/auth/register.js

import bcrypt from "bcryptjs";
import jwt from "jsonwebtoken";

const users = []; // จำลองฐานข้อมูลใน Memory

export default async function handler(req, res) {
  if (req.method !== "POST") return res.status(405).json({ error: "Method Not Allowed" });

  const { email, password, role } = req.body;
  if (!email || !password || !role) return res.status(400).json({ error: "Missing fields" });

  const hashedPassword = await bcrypt.hash(password, 10);
  const newUser = { email, password: hashedPassword, role };
  users.push(newUser);

  res.json({ message: "User registered", user: { email, role } });
}

✅ สมัครสมาชิก พร้อมเก็บ role (เช่น admin หรือ user)

📌 สร้าง API Login (เข้าสู่ระบบ)

📌 ไฟล์: pages/api/auth/login.js

import bcrypt from "bcryptjs";
import jwt from "jsonwebtoken";
import { serialize } from "cookie";

const users = []; // ใช้ฐานข้อมูลจริงในโปรเจกต์จริง

export default async function handler(req, res) {
  if (req.method !== "POST") return res.status(405).json({ error: "Method Not Allowed" });

  const { email, password } = req.body;
  const user = users.find((u) => u.email === email);
  if (!user) return res.status(401).json({ error: "User not found" });

  const isMatch = await bcrypt.compare(password, user.password);
  if (!isMatch) return res.status(401).json({ error: "Invalid password" });

  const token = jwt.sign({ email: user.email, role: user.role }, "SECRET_KEY", { expiresIn: "1h" });

  res.setHeader("Set-Cookie", serialize("auth_token", token, { httpOnly: true, path: "/" }));
  res.json({ message: "Login successful", token });
}

✅ ตรวจสอบรหัสผ่าน และสร้าง JWT Token
✅ เก็บ Token ใน Cookie เพื่อใช้ใน Middleware

🚦 3. สร้าง Middleware เช็ก Role

📌 ไฟล์: middleware/auth.js

import jwt from "jsonwebtoken";
import { parse } from "cookie";

export function withAuth(handler, allowedRoles) {
  return async (req, res) => {
    const cookies = parse(req.headers.cookie || "");
    const token = cookies.auth_token;

    if (!token) return res.status(401).json({ error: "Not authenticated" });

    try {
      const decoded = jwt.verify(token, "SECRET_KEY");
      if (!allowedRoles.includes(decoded.role)) {
        return res.status(403).json({ error: "Access Denied" });
      }

      req.user = decoded; // ส่งข้อมูลผู้ใช้ไปยัง API
      return handler(req, res);
    } catch (error) {
      return res.status(401).json({ error: "Invalid Token" });
    }
  };
}

✅ เช็กว่า JWT ถูกต้อง & Role ตรงกับสิทธิ์ที่กำหนด

🔥 4. สร้าง API แยกสิทธิ์

📌 API เฉพาะ Admin

📌 ไฟล์: pages/api/admin.js

import { withAuth } from "../../middleware/auth";

export default withAuth((req, res) => {
  res.json({ message: "Welcome Admin!", user: req.user });
}, ["admin"]);

✅ เฉพาะ Admin เท่านั้นที่เรียก API นี้ได้

📌 API สำหรับ User & Admin

📌 ไฟล์: pages/api/user.js

import { withAuth } from "../../middleware/auth";

export default withAuth((req, res) => {
  res.json({ message: `Welcome ${req.user.role}!`, user: req.user });
}, ["user", "admin"]);

✅ ทั้ง User & Admin ใช้งานได้


🎨 5. สร้าง UI หน้าเว็บ

📌 ไฟล์: pages/index.js

import { useState } from "react";

export default function Home() {
  const [message, setMessage] = useState("");

  const checkAdmin = async () => {
    const res = await fetch("/api/admin");
    const data = await res.json();
    setMessage(data.message || data.error);
  };

  const checkUser = async () => {
    const res = await fetch("/api/user");
    const data = await res.json();
    setMessage(data.message || data.error);
  };

  return (
    <div>
      <h1>Role-based Authentication</h1>
      <button onClick={checkAdmin}>Check Admin</button>
      <button onClick={checkUser}>Check User</button>
      <p>{message}</p>
    </div>
  );
}

✅ ทดสอบ กดปุ่ม Check Admin หรือ Check User เพื่อดูสิทธิ์



🚀 6. ทดสอบระบบ

  1. รันเซิร์ฟเวอร์ npm run dev
  2. สมัครสมาชิก → /api/auth/register
  3. ล็อกอิน → /api/auth/login
  4. ลองเรียก /api/admin และ /api/user ดูว่า Role ตรงไหม


🎯 สรุป

✅ ใช้ JWT และ Middleware จัดการ Role
✅ แยกสิทธิ์ Admin, User, Guest
✅ ใช้ API แยก Role เพื่อควบคุมสิทธิ์การเข้าถึง

💡 พร้อมใช้กับเว็บจริง! แค่เพิ่ม Database และ UI สวยๆ เท่านั้น! 🚀

วันอาทิตย์ที่ 16 มีนาคม พ.ศ. 2568

การใช้ NextAuth.js สำหรับการล็อกอินในแอป Next.js

ถ้าคุณกำลังพัฒนาเว็บแอปด้วย Next.js แล้วอยากเพิ่มระบบล็อกอินที่ปลอดภัยโดยไม่ต้องปวดหัวกับการจัดการ JWT, OAuth, หรือ Session เอง NextAuth.js คือคำตอบที่คุณต้องการ!

NextAuth.js คืออะไร?

NextAuth.js เป็น authentication library สำหรับ Next.js ที่ทำให้การเพิ่มระบบล็อกอินเป็นเรื่องง่าย รองรับหลาย ๆ provider เช่น Google, Facebook, GitHub, Twitter หรือแม้กระทั่ง credentials-based login (อีเมล/รหัสผ่าน)

จุดเด่นของ NextAuth.js คือ ไม่ต้องเขียน backend เอง เพราะมันใช้ API routes ของ Next.js จัดการ authentication ให้เสร็จสรรพ

ติดตั้ง NextAuth.js

ก่อนอื่น ไปที่โปรเจกต์ Next.js ของคุณ แล้วติดตั้ง NextAuth.js ด้วยคำสั่งนี้:

npm install next-auth
# หรือใช้ yarn
yarn add next-auth

ตั้งค่า NextAuth.js

NextAuth ต้องใช้ API Route ในการจัดการ authentication ดังนั้นเราจะสร้างไฟล์ pages/api/auth/[...nextauth].js (หรือ .ts ถ้าใช้ TypeScript)

ตัวอย่างการตั้งค่า NextAuth.js

import NextAuth from "next-auth";
import GoogleProvider from "next-auth/providers/google";

export default NextAuth({
  providers: [
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET,
    }),
  ],
  secret: process.env.NEXTAUTH_SECRET,
});

💡 อธิบายโค้ดนี้:

  • เราใช้ GoogleProvider เป็น provider สำหรับล็อกอินผ่าน Google
  • ค่า clientId และ clientSecret จะถูกเก็บไว้ในไฟล์ .env.local เพื่อความปลอดภัย
  • NEXTAUTH_SECRET เป็นคีย์สำหรับเข้ารหัส session tokens


ตั้งค่า Environment Variables

สร้างไฟล์ .env.local แล้วใส่ค่าต่อไปนี้ (อย่าลืมเปลี่ยนค่าให้ตรงกับของจริงจาก Google API Console)

GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
NEXTAUTH_SECRET=your-random-secret-key

📌 TIP: ใช้คำสั่งนี้ใน Terminal เพื่อสร้างค่า NEXTAUTH_SECRET แบบสุ่ม

openssl rand -base64 32


เพิ่มปุ่มล็อกอิน/ล็อกเอาต์ในหน้าเว็บ

NextAuth.js มี React Hooks ที่ให้เราดึงสถานะล็อกอินของผู้ใช้มาแสดงผลได้ง่าย ๆ

แก้ไข pages/index.js เพื่อเพิ่มปุ่มล็อกอิน

import { signIn, signOut, useSession } from "next-auth/react";

export default function Home() {
  const { data: session } = useSession();

  return (
    <div>
      {session ? (
        <>
          <p>Welcome, {session.user.name}!</p>
          <img src={session.user.image} alt="Profile" width={50} height={50} />
          <button onClick={() => signOut()}>Sign Out</button>
        </>
      ) : (
        <>
          <p>You are not logged in.</p>
          <button onClick={() => signIn("google")}>Sign in with Google</button>
        </>
      )}
    </div>
  );
}

🔹 อธิบายโค้ดนี้:

  • useSession() ใช้ดึงข้อมูล session ของผู้ใช้
  • ถ้าผู้ใช้ล็อกอินอยู่ จะแสดง ชื่อ และ รูปโปรไฟล์
  • ถ้ายังไม่ได้ล็อกอิน จะแสดงปุ่มให้กดล็อกอินผ่าน Google
  • signIn("google") และ signOut() เป็นฟังก์ชันสำหรับล็อกอินและล็อกเอาต์


ปรับแต่ง NextAuth.js

ถ้าคุณต้องการเพิ่ม database หรือเปลี่ยนแปลง behavior ของ NextAuth.js สามารถแก้ไข pages/api/auth/[...nextauth].js ได้ เช่น
ใช้ Credentials Login (อีเมล/รหัสผ่าน)

import NextAuth from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";

export default NextAuth({
  providers: [
    CredentialsProvider({
      name: "Credentials",
      credentials: {
        email: { label: "Email", type: "email" },
        password: { label: "Password", type: "password" },
      },
      async authorize(credentials) {
        if (credentials.email === "test@example.com" && credentials.password === "password123") {
          return { id: 1, name: "Test User", email: credentials.email };
        }
        return null;
      },
    }),
  ],
  secret: process.env.NEXTAUTH_SECRET,
});

💡 สิ่งที่เพิ่มเข้ามา:

  • CredentialsProvider ให้ผู้ใช้ล็อกอินด้วยอีเมล/รหัสผ่าน
  • ฟังก์ชัน authorize(credentials) ใช้ตรวจสอบข้อมูลผู้ใช้
  • ตอนนี้ใช้เงื่อนไขแบบง่าย ๆ (เช็คอีเมลกับรหัสผ่านตรงกัน) แต่ในโปรดักชันควรใช้ database หรือ hashed password


ใช้ Middleware เพื่อป้องกันหน้าเว็บที่ต้องล็อกอิน

ถ้าคุณต้องการป้องกันบางหน้าให้เฉพาะผู้ใช้ที่ล็อกอินแล้วเข้าถึงได้ สามารถใช้ Middleware ของ Next.js

สร้างไฟล์ middleware.js ที่ root ของโปรเจกต์

import { withAuth } from "next-auth/middleware";

export default withAuth({
  pages: {
    signIn: "/",
  },
});

📌 สิ่งที่ทำได้:

  • ถ้าผู้ใช้ไม่ได้ล็อกอิน จะถูก redirect ไปที่หน้า /
  • ใช้กับ server-side protection ได้ โดยใส่ใน API Routes


สรุป

✅ ติดตั้ง NextAuth.js และเพิ่ม API Route
✅ ตั้งค่า Google OAuth หรือใช้ Credentials Login
✅ เพิ่มปุ่มล็อกอิน/ล็อกเอาต์ ในหน้าเว็บ
✅ ใช้ Middleware เพื่อป้องกันหน้าที่ต้องล็อกอิน

NextAuth.js ทำให้การเพิ่มระบบล็อกอินใน Next.js ง่ายขึ้นมาก! ถ้าคุณต้องการระบบล็อกอินที่ ปลอดภัย, ยืดหยุ่น, และขยายต่อได้ง่าย NextAuth.js คือตัวเลือกที่ดีมากสำหรับคุณ 🚀

วันอังคารที่ 4 มีนาคม พ.ศ. 2568

การใช้งาน Middleware ใน Next.js

ถ้าพูดถึง Middleware หลายคนอาจนึกถึง Express.js ที่ใช้ตรวจสอบ Request ก่อนส่งไปยัง Handler แต่รู้ไหมว่า Next.js ก็มี Middleware เป็นของตัวเอง!

Middleware ใน Next.js ช่วยให้เราสามารถ ควบคุมการเข้าถึงหน้าเว็บ, ตรวจสอบสิทธิ์ (Authentication), Redirect, และ Modify Request/Response ได้ก่อนที่ผู้ใช้จะเข้าถึงหน้าเว็บจริง ๆ

ในบทความนี้ เราจะมาดูกันว่า Middleware ใน Next.js คืออะไร ใช้งานยังไง และเราสามารถนำไปใช้ทำอะไรได้บ้าง 🛠️🚀

🔥 Middleware ใน Next.js คืออะไร?

Middleware คือ โค้ดที่ทำงานอยู่ระหว่าง Request และ Response หรือพูดง่าย ๆ ก็คือ มันช่วยให้เราสามารถจัดการ Request ก่อนที่มันจะไปถึง API หรือ Page จริง ๆ

Next.js Middleware ทำงานที่ Edge หรือที่เรียกว่า Edge Functions ซึ่งหมายความว่า
✅ ทำงานเร็วมาก เพราะไม่ต้องรอโหลดทั้งเซิร์ฟเวอร์
✅ ใช้งานได้กับทุก Request ที่เข้ามา
✅ ลดภาระของ API Routes และ getServerSideProps

📌 ข้อดีของ Middleware

  • ตรวจสอบสิทธิ์ (Auth) ก่อนเข้าหน้าเว็บ
  • กำหนดเงื่อนไขสำหรับแต่ละ Route
  • Redirect หรือ Rewrite Request ได้
  • บล็อกหรือแก้ไข Header ของ Request


🚀 วิธีใช้ Middleware ใน Next.js

Middleware ใน Next.js จะถูกเก็บไว้ที่ไฟล์ middleware.ts หรือ middleware.js ใน root ของโปรเจกต์

🔹 สร้าง Middleware แรกของคุณ

ไฟล์ middleware.ts

import { NextRequest, NextResponse } from 'next/server'

export function middleware(req: NextRequest) {
  console.log('Middleware กำลังทำงาน...')
  return NextResponse.next() // ให้ Request ผ่านไปยังหน้าปลายทาง
}

จากนั้นรันเซิร์ฟเวอร์

npm run dev

ทุกครั้งที่มี Request เข้ามา Middleware จะทำงานก่อนส่งไปที่ Page หรือ API


🔑 ตัวอย่างการใช้งาน Middleware

✨ 1. การ Redirect ผู้ใช้

บางครั้งเราต้องการให้ผู้ใช้ถูก Redirect ไปยังหน้าอื่น โดยอัตโนมัติ

import { NextRequest, NextResponse } from 'next/server'

export function middleware(req: NextRequest) {
  const url = req.nextUrl

  if (url.pathname === '/old-page') {
    return NextResponse.redirect(new URL('/new-page', req.url))
  }

  return NextResponse.next()
}

✅ เมื่อผู้ใช้เข้าหน้า /old-page จะถูก Redirect ไปที่ /new-page อัตโนมัติ

🔐 2. ตรวจสอบสิทธิ์ก่อนเข้าหน้าเว็บ (Authentication)

สมมติว่าเรามีหน้า Dashboard ที่ต้องการให้เฉพาะผู้ใช้ที่ล็อกอินเข้าถึงได้

import { NextRequest, NextResponse } from 'next/server'

export function middleware(req: NextRequest) {
  const token = req.cookies.get('auth_token')

  if (!token) {
    return NextResponse.redirect(new URL('/login', req.url))
  }

  return NextResponse.next()
}

✅ ถ้าไม่มี Token ผู้ใช้จะถูกส่งไปที่ /login ทันที

🌍 3. เช็คประเทศของผู้ใช้ แล้วเปลี่ยนภาษาอัตโนมัติ

ถ้าต้องการ เปลี่ยนภาษาเว็บตามประเทศของผู้ใช้ เราสามารถใช้ Middleware เช็ค IP แล้ว Redirect ไปยังหน้าที่เหมาะสม

import { NextRequest, NextResponse } from 'next/server'

export function middleware(req: NextRequest) {
  const country = req.geo?.country || 'US' // ดึงค่าประเทศจาก IP

  if (country === 'TH') {
    return NextResponse.redirect(new URL('/th', req.url)) // เปลี่ยนไปหน้าเวอร์ชันภาษาไทย
  }

  return NextResponse.next()
}

✅ ถ้าผู้ใช้มาจากไทย จะถูกส่งไปที่ /th อัตโนมัติ

🔄 4. เปลี่ยน Headers ของ Request

บางครั้งเราต้องการ เพิ่ม Headers หรือแก้ไข Headers ก่อนส่งไปยัง API หรือ Page

import { NextRequest, NextResponse } from 'next/server'

export function middleware(req: NextRequest) {
  const response = NextResponse.next()
  response.headers.set('X-Custom-Header', 'HelloMiddleware')
  return response
}

✅ เพิ่ม Header X-Custom-Header: HelloMiddleware ในทุก Response

🛠 การกำหนด Middleware ให้ทำงานเฉพาะบางหน้า

บางครั้งเราอาจต้องการให้ Middleware ทำงาน แค่บางหน้า ไม่ใช่ทั้งหมด สามารถใช้ config.matcher ได้

import { NextRequest, NextResponse } from 'next/server'

export function middleware(req: NextRequest) {
  return NextResponse.next()
}

// ใช้ Middleware เฉพาะบาง Route
export const config = {
  matcher: ['/dashboard/:path*', '/profile/:path*'],
}

✅ Middleware จะทำงานเฉพาะหน้า /dashboard และ /profile เท่านั้น


📌 Middleware กับ API Routes ต่างกันยังไง?

Feature Middleware API Routes
ทำงานเมื่อไหร่? ก่อนส่งไปยัง Page หรือ API เมื่อมีการเรียก API
ทำอะไรได้บ้าง? Redirect, Auth, Modify Request รับ-ส่งข้อมูล API
ทำงานที่ไหน? Edge (เร็วมาก) Server (ปกติ)
ใช้เมื่อไหร่? ตรวจสอบสิทธิ์, Redirect, แก้ไข Headers สร้าง API สำหรับแอป
  • ถ้าต้องการ ดัก Request ก่อนถึงหน้าเว็บ → ใช้ Middleware
  • ถ้าต้องการ สร้าง API Endpoint สำหรับแอป → ใช้ API Routes


🎯 สรุป

Middleware ใน Next.js เป็นเครื่องมือที่ทรงพลังที่ช่วยให้เราสามารถ
✅ Redirect ผู้ใช้ ไปยังหน้าที่เหมาะสม
✅ ตรวจสอบสิทธิ์ ก่อนเข้าถึงข้อมูล
✅ เปลี่ยน Headers ของ Request/Response
✅ ตรวจสอบ IP, Geo Location และเปลี่ยนภาษาเว็บอัตโนมัติ

🔥 ถ้าโปรเจกต์ของคุณต้องการควบคุม Request ก่อนถึงหน้าเว็บ Middleware คือสิ่งที่คุณต้องใช้! 🚀

วันอาทิตย์ที่ 2 มีนาคม พ.ศ. 2568

การใช้ API Routes เพื่อสร้าง Backend ใน Next.js

ถ้าพูดถึง Next.js หลายคนคงนึกถึง Frontend Framework ที่ช่วยพัฒนาเว็บได้เร็วและแรง แต่รู้หรือเปล่าว่า Next.js ก็มี Backend ในตัว ด้วย?

ใช่แล้ว! Next.js มาพร้อมกับ API Routes ที่ให้เราสร้าง Backend API ได้ง่าย ๆ โดยไม่ต้องใช้ Express, NestJS หรือพวก Backend Framework อื่น ๆ

ในบทความนี้ เราจะมาทำความรู้จัก API Routes ใน Next.js ว่ามันคืออะไร ใช้งานยังไง และมีประโยชน์อะไรบ้าง ถ้าพร้อมแล้วไปลุยกันเลย! 🚀

🤔 API Routes คืออะไร?

API Routes คือฟีเจอร์ของ Next.js ที่ให้เราสร้าง REST API ได้โดยตรงในโปรเจกต์ Next.js เอง โดยไม่ต้องเซ็ตเซิร์ฟเวอร์แยก

📌 ข้อดีของ API Routes

✅ ไม่ต้องใช้ Backend แยก – Next.js จัดการให้
✅ ใช้ JavaScript/TypeScript ล้วน ๆ – ไม่ต้องเรียนรู้ภาษาใหม่
✅ รองรับ Serverless Functions – ทำงานบน Vercel, AWS Lambda, Firebase Functions ได้เลย
✅ ใช้ร่วมกับ Frontend ง่าย – อยู่ในโปรเจกต์เดียวกัน

ถ้าเทียบกับการใช้ Node.js + Express ที่ต้องเซ็ตเซิร์ฟเวอร์เอง API Routes ของ Next.js จะง่ายกว่าเยอะ!

🛠 สร้าง API Routes แรกของคุณ

ใน Next.js ไฟล์ API Routes จะอยู่ใน /pages/api/ เช่น

📂 โครงสร้างโฟลเดอร์

my-next-app/
 ├── pages/
 │   ├── index.js
 │   ├── about.js
 │   ├── api/       <-- โฟลเดอร์ API
 │   │   ├── hello.js   <-- ไฟล์ API Route
 │   │   ├── users.js
 │   │   ├── posts.js

ลองสร้างไฟล์ /pages/api/hello.js แล้วใส่โค้ดนี้ลงไป

export default function handler(req, res) {
  res.status(200).json({ message: 'สวัสดีจาก API Routes!' })
}

✨ ลองรันเซิร์ฟเวอร์

npm run dev
# หรือ
yarn dev

แล้วเข้า http://localhost:3000/api/hello จะได้ JSON แบบนี้

{
  "message": "สวัสดีจาก API Routes!"
}

ง่ายมากใช่ไหม? ไม่ต้องติดตั้ง Express หรือเซ็ต Server อะไรให้ยุ่งยากเลย!

🚀 การใช้ HTTP Methods (GET, POST, PUT, DELETE)

API Routes รองรับทุก HTTP Method เช่น GET, POST, PUT, DELETE โดยเช็คจาก req.method

✨ ตัวอย่าง API รองรับหลาย Method

ไฟล์ /pages/api/users.js

export default function handler(req, res) {
  if (req.method === 'GET') {
    res.status(200).json({ users: ['Alice', 'Bob', 'Charlie'] })
  } else if (req.method === 'POST') {
    res.status(201).json({ message: 'สร้างผู้ใช้ใหม่เรียบร้อย!' })
  } else {
    res.status(405).json({ error: 'Method ไม่รองรับ' })
  }
}

🔹 GET → ดึงข้อมูลผู้ใช้
🔹 POST → สร้างผู้ใช้ใหม่
🔹 อื่น ๆ → ส่ง 405 Method Not Allowed

ลองยิง API ดู! 🚀

curl -X GET http://localhost:3000/api/users
curl -X POST http://localhost:3000/api/users


🔄 อ่านค่า Query Parameters

ถ้าต้องการดึงค่าจาก Query String (เช่น /api/user?id=123) เราสามารถใช้ req.query ได้เลย

ไฟล์ /pages/api/user.js

export default function handler(req, res) {
  const { id } = req.query

  if (!id) {
    return res.status(400).json({ error: 'กรุณาระบุ id' })
  }

  res.status(200).json({ user: { id, name: 'John Doe' } })
}

✨ ทดสอบ API

curl http://localhost:3000/api/user?id=456

📌 output

{
  "user": { "id": "456", "name": "John Doe" }
}


📬 รับข้อมูลจาก Body (POST Method)

ถ้าต้องการรับข้อมูลจาก Body ของ Request เช่นเวลาส่งฟอร์มหรือ JSON Data เราสามารถใช้ req.body ได้เลย

ไฟล์ /pages/api/login.js

export default function handler(req, res) {
  if (req.method !== 'POST') {
    return res.status(405).json({ error: 'Method ไม่รองรับ' })
  }

  const { username, password } = req.body

  if (username === 'admin' && password === '1234') {
    res.status(200).json({ message: 'เข้าสู่ระบบสำเร็จ!' })
  } else {
    res.status(401).json({ error: 'ชื่อผู้ใช้หรือรหัสผ่านไม่ถูกต้อง' })
  }
}

✨ ทดสอบ API

curl -X POST http://localhost:3000/api/login -H "Content-Type: application/json" -d '{"username": "admin", "password": "1234"}'

📌 output

{
  "message": "เข้าสู่ระบบสำเร็จ!"
}

🔒 ใช้ Middleware กับ API Routes

ถ้าต้องการตรวจสอบ JWT Token หรือทำ Authentication ก่อนเข้าถึง API สามารถใช้ Middleware ได้ง่าย ๆ

ไฟล์ /pages/api/secure.js

export default function handler(req, res) {
  const { authorization } = req.headers

  if (!authorization || authorization !== 'Bearer mysecrettoken') {
    return res.status(403).json({ error: 'ไม่ได้รับอนุญาต' })
  }

  res.status(200).json({ message: 'เข้าถึงข้อมูลสำเร็จ!' })
}

✨ ทดสอบ API (ล้มเหลว)

curl http://localhost:3000/api/secure

📌 output

{
  "error": "ไม่ได้รับอนุญาต"
}

✨ ทดสอบ API (สำเร็จ)

curl -H "Authorization: Bearer mysecrettoken" http://localhost:3000/api/secure

📌 output

{
  "message": "เข้าถึงข้อมูลสำเร็จ!"
}

🎯 สรุป

API Routes เป็นฟีเจอร์ที่ช่วยให้เราสร้าง Backend API ใน Next.js ได้ง่าย ๆ โดยไม่ต้องติดตั้งเซิร์ฟเวอร์แยก เหมาะกับการทำงานแบบ Fullstack ที่ต้องการพัฒนา Frontend และ Backend ไปพร้อมกัน

📌 จุดเด่นของ API Routes

✅ ใช้งานง่าย – ไม่ต้องเซ็ตเซิร์ฟเวอร์เอง
✅ รองรับ HTTP Methods (GET, POST, PUT, DELETE)
✅ ใช้ Query Parameters และ Request Body ได้
✅ รองรับ Middleware เช่น Authentication

ถ้าคุณใช้ Next.js อยู่แล้ว ลองใช้ API Routes ดู แล้วจะรู้ว่ามัน โคตรสะดวก! 🚀

วันอังคารที่ 18 กุมภาพันธ์ พ.ศ. 2568

การใช้งาน pages/ และการสร้าง Routing อัตโนมัติใน Next.js

ถ้าคุณเป็นสายเว็บที่อยากเขียนเว็บเร็ว ๆ ไม่ต้องมานั่งเซ็ต Routing เองให้ปวดหัว Next.js คือเพื่อนที่คุณต้องการ! หนึ่งในฟีเจอร์เด็ดของมันคือการใช้โฟลเดอร์ pages/ เพื่อสร้าง Routing แบบอัตโนมัติ ที่จะทำให้ชีวิตของคุณง่ายขึ้น ไม่ต้องมานั่งเขียนไฟล์ routes.js หรือกำหนด path เองแบบสมัยก่อน

บทความนี้จะพาคุณไปทำความเข้าใจว่า โฟลเดอร์ pages/ ใน Next.js ทำงานยังไง, จะใช้มันให้เกิดประโยชน์สูงสุดได้ยังไง, และ ถ้าคุณอยากใช้ Dynamic Routing หรือ API Routes ต้องทำยังไง มาเริ่มกันเลย!

 

พื้นฐานของโฟลเดอร์ pages/

ใน Next.js โฟลเดอร์ pages/ เป็นศูนย์กลางของระบบ Routing ทั้งหมด มันทำงานง่าย ๆ คือ "มีไฟล์อะไรใน pages/ ก็จะมี URL ตามไฟล์นั้น" เช่น

  • pages/index.js → /
  • pages/about.js → /about
  • pages/contact.js → /contact

แค่สร้างไฟล์ .js หรือ .tsx ในโฟลเดอร์นี้ Next.js ก็จะสร้างเส้นทางให้โดยอัตโนมัติ ไม่ต้องเขียนโค้ดอะไรเพิ่ม!

ตัวอย่างไฟล์ pages/about.js 

export default function AboutPage() {
  return <h1>นี่คือหน้า About</h1>;
}

พอสร้างไฟล์นี้เสร็จ คุณสามารถเข้าเว็บที่ /about ได้เลยโดยไม่ต้องตั้งค่าอะไรเพิ่ม!


สร้าง Routing อัตโนมัติแบบง่าย ๆ

การสร้างหน้าใหม่

ถ้าอยากเพิ่มหน้าใหม่ ก็แค่สร้างไฟล์ใหม่ใน pages/ เท่านั้น เช่น

mkdir pages/blog
touch pages/blog/index.js

จากนั้นเพิ่มโค้ดง่าย ๆ

export default function BlogPage() {
  return <h1>ยินดีต้อนรับสู่หน้า Blog!</h1>;
}

แค่นี้คุณก็สามารถเข้าหน้า /blog ได้แล้ว ไม่ต้องไปแก้ไขอะไรเพิ่มเติมเลย 

 

Dynamic Routing: เส้นทางที่ยืดหยุ่นกว่านี้มีอีกไหม? มี!

สมมติว่าคุณอยากสร้างหน้า Blog ที่สามารถรองรับโพสต์หลาย ๆ อัน เช่น /blog/post-1, /blog/post-2 โดยไม่ต้องสร้างไฟล์ใหม่ให้แต่ละโพสต์เอง เราสามารถใช้ Dynamic Routing ได้โดยใช้เครื่องหมาย [] ในชื่อไฟล์

ตัวอย่าง:
สร้างไฟล์ pages/blog/[slug].js

import { useRouter } from 'next/router';

export default function BlogPostPage() {
  const router = useRouter();
  const { slug } = router.query;

  return <h1>กำลังอ่านบทความ: {slug}</h1>;
}

เมื่อมีคนเข้าไปที่ /blog/my-first-post หรือ /blog/hello-world ค่า {slug} จะเปลี่ยนไปตาม URL อัตโนมัติ

 

API Routes: ใช้ pages/api/ เพื่อสร้าง API ง่าย ๆ

Next.js ไม่ได้ใช้ pages/ แค่สำหรับสร้างหน้าเว็บเท่านั้น มันยังสามารถใช้สำหรับสร้าง API ได้อีกด้วย!

ถ้าคุณสร้างไฟล์ pages/api/hello.js และเขียนโค้ดแบบนี้:

export default function handler(req, res) {
  res.status(200).json({ message: "Hello from API!" });
}

ตอนนี้คุณสามารถเรียก API นี้ได้ที่ /api/hello โดยไม่ต้องตั้งค่าเพิ่ม 


Middleware และการ Redirect Routing

ถ้าคุณอยากควบคุม Routing แบบละเอียดขึ้น Next.js ก็มีเครื่องมือให้ เช่น Middleware และ Redirects

Middleware ช่วยให้คุณสามารถจัดการกับ Request ก่อนที่มันจะไปถึงหน้าเว็บ เช่น ตรวจสอบสิทธิ์การเข้าถึง

ตัวอย่าง Middleware

สร้างไฟล์ middleware.js

import { NextResponse } from "next/server";

export function middleware(req) {
  const url = req.nextUrl.clone();
  if (!req.cookies.auth) {
    url.pathname = "/login";
    return NextResponse.redirect(url);
  }
  return NextResponse.next();
}

จากนั้นกำหนดให้ Middleware ทำงานใน next.config.js

module.exports = {
  async redirects() {
    return [
      {
        source: "/old-page",
        destination: "/new-page",
        permanent: true,
      },
    ];
  },
};
 

ข้อดีของระบบ Routing อัตโนมัติใน Next.js

  • ลดโค้ดที่ต้องเขียน – ไม่ต้องมานั่งเซ็ตเส้นทางเอง
  • SEO-Friendly – เส้นทางแบบ Static และ Dynamic ทำงานได้ดี
  • มี API Routes ในตัว – ไม่ต้องแยก Backend ออกมาเอง
  • รองรับ Dynamic Routing – เหมาะกับเว็บที่มีเนื้อหาหลายหน้า
  • สรุป: Next.js ทำให้ Routing ง่ายขึ้นเยอะ!


ระบบ Routing ใน Next.js ออกแบบมาให้ใช้ง่ายสุด ๆ แค่สร้างไฟล์ในโฟลเดอร์ pages/ ก็สามารถเข้าถึง URL นั้นได้เลย ไม่ต้องตั้งค่าอะไรเพิ่มเติม

ถ้าคุณต้องการ Routing ที่ซับซ้อนขึ้น เช่น Dynamic Routes หรือ API Routes Next.js ก็รองรับทั้งหมดโดยไม่ต้องพึ่ง Third-party library เลย 

พร้อมจะใช้ Next.js ในโปรเจกต์ของคุณหรือยัง? ถ้าพร้อมแล้ว ลองเล่นกับ pages/ ดูเลย แล้วคุณจะติดใจ! 

การใช้ Image Optimization ใน Next.js: โหลดไว SEO ดี ประหยัดแบนด์วิธ!

เคยเจอปัญหาเว็บโหลดช้าเพราะรูปภาพขนาดใหญ่หรือเปล่า? 📷 ถ้าใช่ Next.js มีฟีเจอร์ Image Optimization ที่ช่วยให้รูปภาพโหลดเร็วขึ้น อัตโนมัติ ไม...