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

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

การจัดการ Authentication กับฐานข้อมูล ใน Next.js

การสร้างระบบ Authentication หรือการยืนยันตัวตนในแอปพลิเคชันเว็บคือขั้นตอนที่สำคัญที่สุดขั้นตอนหนึ่งในการพัฒนาเว็บแอป เพราะไม่ว่าระบบนั้นจะเป็นระบบที่ให้ผู้ใช้ทำการสมัครสมาชิก เข้าสู่ระบบ หรือแม้แต่การเข้าถึงข้อมูลส่วนตัว การมีระบบที่สามารถจัดการ Authentication ได้ดีจะช่วยให้การใช้งานระบบมีความปลอดภัย และมั่นใจได้ว่า ผู้ใช้ที่เข้ามาจะต้องมีสิทธิ์ ในการใช้งานตามที่กำหนด

สำหรับ Next.js ซึ่งเป็น framework ที่พัฒนาโดย React, การจัดการ Authentication ถือเป็นส่วนที่สำคัญ โดยเฉพาะอย่างยิ่งเมื่อเราต้องทำการจัดการกับฐานข้อมูล เช่น MySQL, MongoDB หรือ PostgreSQL ซึ่งในบทความนี้เราจะพูดถึงวิธีการจัดการ Authentication บน Next.js ด้วยการเชื่อมต่อกับฐานข้อมูล โดยใช้เครื่องมือที่นิยมอย่าง bcrypt และ JWT (JSON Web Token) เพื่อให้ผู้ใช้สามารถลงทะเบียน เข้าสู่ระบบ และสามารถเข้าถึงข้อมูลที่มีการรักษาความปลอดภัยได้

เริ่มต้นสร้างโปรเจคใน Next.js

ก่อนที่เราจะเริ่มต้นการสร้างระบบ Authentication ด้วย Next.js เราต้องสร้างโปรเจค Next.js ขึ้นมาก่อน และติดตั้งแพ็กเกจที่จำเป็นบางตัว ซึ่งในที่นี้เราจะใช้ bcryptjs สำหรับการเข้ารหัสรหัสผ่าน, jsonwebtoken (JWT) สำหรับการสร้างและจัดการ Token, และ Prisma หรือ Sequelize สำหรับการจัดการกับฐานข้อมูล

1. สร้างโปรเจค Next.js

การสร้างโปรเจค Next.js เป็นขั้นตอนที่ง่ายมาก เพียงแค่ใช้คำสั่งต่อไปนี้ในเทอร์มินัล:

npx create-next-app@latest my-auth-app
cd my-auth-app

เมื่อสร้างโปรเจคเสร็จแล้ว ให้ทำการติดตั้ง dependencies ที่จำเป็น:

npm install bcryptjs jsonwebtoken prisma @prisma/client

2. ตั้งค่า Prisma สำหรับฐานข้อมูล


ถ้าคุณเลือกใช้ Prisma ในการจัดการฐานข้อมูลคุณต้องทำการตั้งค่า Prisma เพื่อเชื่อมต่อกับฐานข้อมูลที่คุณใช้ เช่น MySQL, PostgreSQL, หรือ SQLite ต่อไปนี้คือการตั้งค่าพื้นฐานสำหรับ Prisma:
  • สร้างไฟล์ schema.prisma ที่อยู่ในโฟลเดอร์ prisma สำหรับกำหนดโครงสร้างของฐานข้อมูล

npx prisma init


  • จากนั้นแก้ไขไฟล์ schema.prisma เพื่อกำหนด Model สำหรับผู้ใช้:

model User {
  id        Int    @id @default(autoincrement())
  email     String @unique
  password  String
  createdAt DateTime @default(now())
}


  • หลังจากที่ตั้งค่าฐานข้อมูลเสร็จแล้ว ให้ทำการ Migrate โครงสร้างฐานข้อมูล:
npx prisma migrate dev --name init

ตอนนี้คุณก็พร้อมที่จะใช้ Prisma ในการติดต่อกับฐานข้อมูลแล้ว

การลงทะเบียนผู้ใช้ (Registration)

ในการสร้างระบบการลงทะเบียนเราต้องให้ผู้ใช้กรอกข้อมูล เช่น อีเมล และ รหัสผ่าน โดยระบบจะทำการเข้ารหัสรหัสผ่านก่อนเก็บลงในฐานข้อมูล เพื่อให้ปลอดภัยจากการโจมตีต่างๆ โดยการใช้ bcryptjs ในการเข้ารหัสรหัสผ่านก่อนเก็บ

ตัวอย่างการลงทะเบียนผู้ใช้ใน Next.js API route

// pages/api/auth/register.js
import bcrypt from 'bcryptjs';
import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

export default async function handler(req, res) {
  if (req.method === 'POST') {
    const { email, password } = req.body;

    // ตรวจสอบว่าอีเมลมีอยู่ในฐานข้อมูลหรือไม่
    const existingUser = await prisma.user.findUnique({
      where: { email },
    });

    if (existingUser) {
      return res.status(400).json({ message: 'User already exists' });
    }

    // เข้ารหัสรหัสผ่านก่อนเก็บ
    const hashedPassword = await bcrypt.hash(password, 12);

    // สร้างผู้ใช้ใหม่ในฐานข้อมูล
    const newUser = await prisma.user.create({
      data: {
        email,
        password: hashedPassword,
      },
    });

    return res.status(201).json(newUser);
  } else {
    res.status(405).json({ message: 'Method not allowed' });
  }
}

ในโค้ดนี้เราทำการตรวจสอบว่าอีเมลของผู้ใช้ที่กรอกมีอยู่ในฐานข้อมูลหรือไม่ ถ้ามีระบบจะแจ้งว่าผู้ใช้นั้นมีอยู่แล้ว แต่ถ้าไม่มีก็จะทำการเข้ารหัสรหัสผ่านและสร้างผู้ใช้ใหม่ในฐานข้อมูล

การล็อกอินผู้ใช้ (Login)

เมื่อผู้ใช้ทำการล็อกอิน เราต้องตรวจสอบว่าอีเมลและรหัสผ่านที่กรอกเข้ามาถูกต้องหรือไม่ โดยการเปรียบเทียบรหัสผ่านที่กรอกกับรหัสผ่านที่ถูกเข้ารหัสไว้ในฐานข้อมูล จากนั้น ถ้าถูกต้อง เราจะสร้าง JWT (JSON Web Token) เพื่อใช้ในการยืนยันตัวตนของผู้ใช้ในคำขอต่อไป

ตัวอย่างการล็อกอินใน Next.js API route

// pages/api/auth/login.js
import bcrypt from 'bcryptjs';
import jwt from 'jsonwebtoken';
import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

export default async function handler(req, res) {
  if (req.method === 'POST') {
    const { email, password } = req.body;

    // ค้นหาผู้ใช้ในฐานข้อมูล
    const user = await prisma.user.findUnique({
      where: { email },
    });

    if (!user) {
      return res.status(400).json({ message: 'User not found' });
    }

    // เปรียบเทียบรหัสผ่าน
    const isPasswordValid = await bcrypt.compare(password, user.password);
    if (!isPasswordValid) {
      return res.status(400).json({ message: 'Invalid password' });
    }

    // สร้าง JWT Token
    const token = jwt.sign({ userId: user.id }, 'your_jwt_secret', {
      expiresIn: '1h',
    });

    return res.status(200).json({ token });
  } else {
    res.status(405).json({ message: 'Method not allowed' });
  }
}

ในโค้ดนี้:

  1. ระบบจะค้นหาผู้ใช้จาก อีเมล ที่ผู้ใช้กรอก
  2. ถ้าพบผู้ใช้, ระบบจะทำการเปรียบเทียบ รหัสผ่านที่กรอก กับ รหัสผ่านที่เข้ารหัส ในฐานข้อมูล
  3. ถ้ารหัสผ่านถูกต้อง, ระบบจะสร้าง JWT Token และส่งกลับไปให้ผู้ใช้


การใช้งาน Token ในการยืนยันตัวตน

หลังจากที่ผู้ใช้ล็อกอินสำเร็จและได้รับ JWT Token, ผู้ใช้จะต้องส่ง Token นี้กลับมาในคำขอถัดไป เพื่อให้ระบบสามารถยืนยันตัวตนของผู้ใช้ได้

ตัวอย่างการป้องกัน API ด้วย JWT

// pages/api/protected.js
import jwt from 'jsonwebtoken';

export default function handler(req, res) {
  const token = req.headers['authorization']?.split(' ')[1];

  if (!token) {
    return res.status(401).json({ message: 'No token provided' });
  }

  try {
    const decoded = jwt.verify(token, 'your_jwt_secret');
    res.status(200).json({ message: 'This is a protected route', userId: decoded.userId });
  } catch (error) {
    res.status(401).json({ message: 'Invalid or expired token' });
  }
}

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

สรุป

การจัดการ Authentication ใน Next.js เป็นกระบวนการที่ไม่ซับซ้อนและสามารถทำได้อย่างมีประสิทธิภาพ โดยใช้เครื่องมือที่ได้รับความนิยม เช่น bcryptjs สำหรับการเข้ารหัสรหัสผ่าน และ JWT สำหรับการสร้างและตรวจสอบ Token ซึ่งช่วยให้ระบบของเรามีความปลอดภัยและยืดหยุ่น

การใช้ Prisma ในการเชื่อมต่อฐานข้อมูลก็ทำให้การจัดการข้อมูลผู้ใช้มีความสะดวกและสามารถขยายได้ตามต้องการ โดยทั้งหมดนี้จะทำให้การสร้างระบบ Authentication ใน Next.js เป็นไปอย่างราบรื่นและปลอดภัย

วันศุกร์ที่ 14 มีนาคม พ.ศ. 2568

วิธีสร้าง GraphQL API ด้วย Next.js

ในยุคของการพัฒนาเว็บแอปพลิเคชัน, การเลือกใช้ GraphQL เป็น API ในการจัดการข้อมูลนั้นกำลังได้รับความนิยมมากขึ้นเรื่อยๆ เพราะความยืดหยุ่นและประสิทธิภาพในการดึงข้อมูลที่เป็นประโยชน์ต่อทั้งฝั่งเซิร์ฟเวอร์และไคลเอนต์ อย่างไรก็ตาม, เมื่อเราพูดถึงการสร้าง GraphQL API ใน Next.js, หลายคนอาจจะรู้สึกว่าเป็นเรื่องที่ยากและซับซ้อน เพราะเราต้องทำงานกับ GraphQL และทำความเข้าใจกับวิธีการตั้งค่าและการเชื่อมต่อกับฐานข้อมูล แต่จริงๆ แล้วการสร้าง GraphQL API ใน Next.js นั้นไม่ยากอย่างที่คิด!

ในบทความนี้, เราจะมาพูดถึงวิธีการ สร้าง GraphQL API ด้วย Next.js ซึ่งจะช่วยให้คุณสามารถสร้าง API ที่มีประสิทธิภาพและมีความยืดหยุ่นสูงในการจัดการข้อมูลจากฐานข้อมูล รวมถึงการใช้งานในแอปพลิเคชันที่ซับซ้อนได้อย่างง่ายดาย

ทำไมต้องใช้ GraphQL?

ก่อนที่จะเริ่มสร้าง GraphQL API, มาทำความเข้าใจกันก่อนว่า ทำไม GraphQL ถึงเป็นตัวเลือกที่ดี สำหรับการพัฒนา API:

  1. ดึงข้อมูลตามที่ต้องการ (Query-based): GraphQL ช่วยให้คุณสามารถดึงข้อมูลจากเซิร์ฟเวอร์ได้เฉพาะส่วนที่คุณต้องการ ซึ่งช่วยลดการขอข้อมูลที่ไม่จำเป็นและเพิ่มประสิทธิภาพ
  2. การเรียกข้อมูลหลายๆ ชุดในคำขอเดียว (Multiple Resources): คุณสามารถดึงข้อมูลจากหลายๆ แหล่งในคำขอเดียว ซึ่งช่วยลดจำนวนคำขอที่ต้องทำไปยังเซิร์ฟเวอร์
  3. การทำงานกับข้อมูลที่ซับซ้อน: GraphQL ทำให้การจัดการข้อมูลที่มีความซับซ้อน (เช่น ความสัมพันธ์ระหว่างตารางในฐานข้อมูล) ง่ายขึ้น
  4. การใช้งานที่ยืดหยุ่นและปรับขนาดได้ดี: GraphQL สามารถปรับแต่งให้เหมาะสมกับขนาดและความซับซ้อนของแอปพลิเคชันได้ง่าย


ขั้นตอนการสร้าง GraphQL API ด้วย Next.js

1. การติดตั้งเครื่องมือที่จำเป็น

ก่อนที่เราจะเริ่มสร้าง GraphQL API, เราต้องติดตั้งเครื่องมือและไลบรารีที่จำเป็นในการทำงานกับ GraphQL ใน Next.js ก่อน โดยใช้คำสั่ง:

npx create-next-app@latest my-next-graphql-app
cd my-next-graphql-app

หลังจากที่สร้างโปรเจกต์เสร็จแล้ว, เราต้องติดตั้งไลบรารีที่ช่วยในการทำงานกับ GraphQL โดยใช้คำสั่ง:

npm install apollo-server-micro graphql

  • apollo-server-micro คือไลบรารีสำหรับการสร้าง GraphQL API ที่ทำงานร่วมกับ Next.js ได้ดี
  • graphql เป็นไลบรารีหลักสำหรับการทำงานกับ GraphQL ใน Node.js


2. การตั้งค่า Apollo Server ใน Next.js

ในขั้นตอนนี้, เราจะตั้งค่า Apollo Server เพื่อให้สามารถรับคำขอ GraphQL จากลูกค้าได้ โดยการใช้ Apollo Server Micro ที่เหมาะสำหรับการทำงานในสภาพแวดล้อม serverless อย่าง Next.js

สร้างไฟล์ pages/api/graphql.js:

import { ApolloServer, gql } from 'apollo-server-micro';

// กำหนด Schema ของ GraphQL
const typeDefs = gql`
  type Query {
    hello: String
  }
`;

// กำหนด Resolvers สำหรับการดึงข้อมูล
const resolvers = {
  Query: {
    hello: () => {
      return 'Hello, world!';
    },
  },
};

// สร้าง Apollo Server
const apolloServer = new ApolloServer({
  typeDefs,
  resolvers,
});

// เปิดใช้งาน Apollo Server
const startServer = apolloServer.start();

export default async function handler(req, res) {
  await startServer;
  return apolloServer.createHandler({
    path: '/api/graphql',
  })(req, res);
}

export const config = {
  api: {
    bodyParser: false,
  },
};

ในตัวอย่างนี้, เรากำหนด GraphQL Schema โดยใช้ typeDefs ซึ่งในที่นี้มี Query hello ที่ส่งกลับข้อความ "Hello, world!". เรากำหนด Resolvers ที่ใช้ในการดึงข้อมูลจาก GraphQL ซึ่งในที่นี้จะส่งกลับข้อความที่เรากำหนดไว้

3. การทดสอบ API ด้วย GraphQL Playground

ในตอนนี้, เราสามารถเปิดโปรเจกต์ของเราและทดสอบ GraphQL API ผ่าน GraphQL Playground หรือเครื่องมืออื่นๆ ที่รองรับ GraphQL

หลังจากที่คุณเริ่มต้นเซิร์ฟเวอร์ Next.js แล้ว (โดยการรันคำสั่ง npm run dev), ไปที่ http://localhost:3000/api/graphql ในเบราว์เซอร์ของคุณเพื่อเข้าถึง GraphQL Playground ที่คุณสามารถทดสอบคำขอ GraphQL ได้

ตัวอย่างคำขอ GraphQL:

query {
  hello
}

ผลลัพธ์ที่ได้จะเป็น:

{
  "data": {
    "hello": "Hello, world!"
  }
}

4. การเชื่อมต่อ GraphQL กับฐานข้อมูล

ต่อไปเราจะเชื่อมต่อ GraphQL API กับฐานข้อมูลเพื่อให้สามารถดึงข้อมูลจากฐานข้อมูลได้ ตัวอย่างนี้เราจะใช้ Prisma ORM สำหรับการเชื่อมต่อกับฐานข้อมูล MySQL

ติดตั้ง Prisma:

npm install prisma @prisma/client

จากนั้น, ตั้งค่าฐานข้อมูลของเราในไฟล์ prisma/schema.prisma:

datasource db {
  provider = "mysql"
  url      = env("DATABASE_URL")
}

generator client {
  provider = "prisma-client-js"
}

เมื่อเราได้ตั้งค่า prisma/schema.prisma แล้ว, ให้ใช้คำสั่งนี้เพื่อสร้าง Prisma Client:

npx prisma generate


5. การแก้ไข GraphQL Schema และ Resolvers สำหรับฐานข้อมูล

ตอนนี้เราจะสร้าง GraphQL schema และ resolvers สำหรับการดึงข้อมูลจากฐานข้อมูล

อัปเดต pages/api/graphql.js:

import { ApolloServer, gql } from 'apollo-server-micro';
import prisma from '../../lib/prisma'; // เชื่อมต่อกับ Prisma Client

// กำหนด GraphQL Schema สำหรับการดึงข้อมูลผู้ใช้
const typeDefs = gql`
  type User {
    id: Int
    name: String
    email: String
  }

  type Query {
    users: [User]
  }
`;

// สร้าง Resolver สำหรับการดึงข้อมูลผู้ใช้จากฐานข้อมูล
const resolvers = {
  Query: {
    users: async () => {
      return await prisma.user.findMany(); // ดึงข้อมูลผู้ใช้ทั้งหมดจากฐานข้อมูล
    },
  },
};

// สร้าง Apollo Server
const apolloServer = new ApolloServer({
  typeDefs,
  resolvers,
});

const startServer = apolloServer.start();

export default async function handler(req, res) {
  await startServer;
  return apolloServer.createHandler({
    path: '/api/graphql',
  })(req, res);
}

export const config = {
  api: {
    bodyParser: false,
  },
};

ในตัวอย่างนี้, เราได้เพิ่ม GraphQL Type สำหรับ User และ Query สำหรับดึงข้อมูลผู้ใช้ทั้งหมดจากฐานข้อมูล MySQL โดยใช้ Prisma

6. การทดสอบการดึงข้อมูลจากฐานข้อมูล

หลังจากที่เราได้อัปเดต GraphQL API แล้ว, เราสามารถทดสอบการดึงข้อมูลผู้ใช้จากฐานข้อมูลได้

ตัวอย่างคำขอ:

query {
  users {
    id
    name
    email
  }
}

ผลลัพธ์ที่ได้จะเป็น:

{
  "data": {
    "users": [
      {
        "id": 1,
        "name": "John Doe",
        "email": "johndoe@example.com"
      },
      {
        "id": 2,
        "name": "Jane Doe",
        "email": "janedoe@example.com"
      }
    ]
  }
}

7. การปรับปรุงและเพิ่มฟีเจอร์

หลังจากที่เราสร้าง GraphQL API ที่เชื่อมต่อกับฐานข้อมูลได้แล้ว, คุณสามารถขยาย API ของคุณเพื่อรองรับฟีเจอร์ต่างๆ เช่น การเพิ่มผู้ใช้ใหม่, การอัปเดตข้อมูล, การลบข้อมูล, และการทำงานกับข้อมูลที่มีความสัมพันธ์กัน

ตัวอย่างการเพิ่มผู้ใช้ใหม่:

const resolvers = {
  Mutation: {
    addUser: async (_, { name, email }) => {
      return await prisma.user.create({
        data: { name, email },
      });
    },
  },
};

สรุป

การสร้าง GraphQL API ด้วย Next.js นั้นไม่ยากอย่างที่คิด คุณสามารถใช้ Apollo Server ร่วมกับ Prisma และฐานข้อมูลต่างๆ เพื่อสร้าง API ที่ยืดหยุ่นและมีประสิทธิภาพ ในบทความนี้เราครอบคลุมการสร้าง GraphQL API สำหรับการดึงข้อมูลผู้ใช้จากฐานข้อมูล, และคุณยังสามารถขยายไปใช้ฟีเจอร์อื่นๆ ได้ตามต้องการ

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

การใช้ Supabase กับ Next.js

ทำไมต้อง Supabase?

ถ้าพูดถึงการทำแอปเว็บที่ต้องมีฐานข้อมูล การสมัครสมาชิก หรือ API แบบง่าย ๆ แต่ทรงพลัง Supabase นี่แหละคือของดีที่ควรลอง เพราะมันให้บริการ Backend-as-a-Service (BaaS) ที่ทำงานคล้าย Firebase แต่ใช้ PostgreSQL เป็นฐานข้อมูลหลัก ซึ่งหมายความว่าได้ทั้ง SQL แท้ ๆ และพลังของ Firebase มารวมกัน!

จุดเด่นของ Supabase:

  • ฐานข้อมูล PostgreSQL แบบ Managed (ไม่ต้องตั้งค่าจุกจิก)
  • Authentication ที่รองรับ OAuth, Email/Password และ Magic Links
  • Realtime Database สามารถ Subscriptions เหมือน Firebase
  • Storage สำหรับเก็บไฟล์ เช่น รูปหรือวิดีโอ
  • Edge Functions สำหรับสร้าง API แบบ Serverless
  • ใช้งานฟรีในระดับเริ่มต้น!


ทำไม Next.js ถึงเป็นตัวเลือกที่ดี?

ถ้า Supabase เป็นขุมพลังฝั่ง Backend งั้นฝั่ง Frontend ที่มาเข้าคู่กันได้ดีสุดก็คือ Next.js นี่แหละ ด้วยความสามารถแบบ Full-Stack ที่ให้เราสร้าง API Routes, Server-side Rendering (SSR), Static Site Generation (SSG) และ Client-side Rendering (CSR) ได้ในโปรเจกต์เดียวกัน ทำให้สามารถใช้ Supabase ได้เต็มประสิทธิภาพสุด ๆ

มาเริ่มใช้ Supabase กับ Next.js กันเถอะ!

1. สร้างโปรเจกต์ Next.js

เริ่มจากการสร้างโปรเจกต์ Next.js กันก่อน ใช้คำสั่งนี้ใน Terminal:

npx create-next-app@latest my-supabase-app
cd my-supabase-app
npm install

2. ติดตั้ง Supabase SDK

เมื่อมีโปรเจกต์ Next.js แล้ว เราต้องเพิ่ม Supabase SDK เข้าไป:

npm install @supabase/supabase-js

3. ตั้งค่า Supabase Client

Supabase ต้องการ API URL และ Anon Key ซึ่งเราจะได้มาจาก supabase.com หลังจากสมัครและสร้างโปรเจกต์ใหม่

ให้สร้างไฟล์ .env.local แล้วใส่ค่าแบบนี้:

NEXT_PUBLIC_SUPABASE_URL=your-supabase-url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key

จากนั้นสร้าง utils/supabaseClient.js เพื่อเชื่อมต่อ Supabase:

import { createClient } from '@supabase/supabase-js';

const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL;
const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY;

export const supabase = createClient(supabaseUrl, supabaseAnonKey);

4. การสมัครสมาชิกและล็อกอินด้วย Supabase Auth

ใน Next.js เราสามารถใช้ Supabase Auth เพื่อให้ผู้ใช้ สมัครสมาชิก, ล็อกอิน และออกจากระบบ ได้ง่าย ๆ

สมัครสมาชิก

import { supabase } from '../utils/supabaseClient';

async function signUp(email, password) {
  const { user, error } = await supabase.auth.signUp({ email, password });
  if (error) {
    console.error(error.message);
  } else {
    console.log('User signed up:', user);
  }
}

ล็อกอิน

async function signIn(email, password) {
  const { user, error } = await supabase.auth.signInWithPassword({ email, password });
  if (error) {
    console.error(error.message);
  } else {
    console.log('User signed in:', user);
  }
}

ออกจากระบบ

async function signOut() {
  const { error } = await supabase.auth.signOut();
  if (error) {
    console.error(error.message);
  } else {
    console.log('User signed out');
  }
}

5. การใช้ Realtime Database

หนึ่งในจุดแข็งของ Supabase คือ Realtime Database ซึ่งช่วยให้เราติดตามการเปลี่ยนแปลงของข้อมูลได้ทันที

ตัวอย่างการ Subscriptions ตาราง messages:

import { useEffect, useState } from 'react';
import { supabase } from '../utils/supabaseClient';

export default function Chat() {
  const [messages, setMessages] = useState([]);

  useEffect(() => {
    const subscription = supabase
      .channel('messages')
      .on('postgres_changes', { event: '*', schema: 'public', table: 'messages' }, (payload) => {
        setMessages((prevMessages) => [...prevMessages, payload.new]);
      })
      .subscribe();
    return () => {
      supabase.removeChannel(subscription);
    };
  }, []);

  return (
    <div>
      {messages.map((msg, index) => (
        <p key={index}>{msg.content}</p>
      ))}
    </div>
  );
}

6. การใช้ Supabase Storage

ถ้าอยากอัปโหลดไฟล์ภาพไปเก็บไว้บน Supabase ก็ทำได้ง่าย ๆ

async function uploadFile(file) {
  const { data, error } = await supabase.storage.from('avatars').upload(`public/${file.name}`, file);
  if (error) {
    console.error('Upload error:', error.message);
  } else {
    console.log('Uploaded file:', data);
  }
}

7. การสร้าง API ด้วย Supabase Edge Functions

ถ้าต้องการ API แบบ Serverless ก็สามารถใช้ Edge Functions ของ Supabase ได้ โดยเขียนฟังก์ชันใน TypeScript และ Deploy ไปยัง Supabase

import { serve } from 'std/server';
export default serve(async (req) => {
  return new Response('Hello from Supabase Edge Function!');
});

สรุป

Supabase เป็นตัวเลือกที่ยอดเยี่ยมสำหรับการทำ Full-Stack Development กับ Next.js เพราะมันให้เราสร้างแอปพลิเคชันที่มี Authentication, Database, Storage และ Realtime ได้ง่ายมาก ๆ ถ้าคุณกำลังหา Backend ที่ใช้ง่าย แต่ทรงพลัง บอกเลยว่า Supabase คือทางเลือกที่ดี!

วันพฤหัสบดีที่ 6 มีนาคม พ.ศ. 2568

การเชื่อมต่อ PostgreSQL กับ Next.js: ทำเว็บให้มี Database กันเถอะ!

ถ้าคุณกำลังทำเว็บด้วย Next.js แล้วอยากให้มัน เก็บข้อมูล ได้จริง ๆ ไม่ใช่แค่โชว์ข้อมูลสวย ๆ การเชื่อมต่อกับ PostgreSQL เป็นหนึ่งในทางเลือกที่ดีมาก! 🔥

PostgreSQL (หรือที่เรียกสั้น ๆ ว่า Postgres) เป็นฐานข้อมูลเชิงสัมพันธ์ (Relational Database) ที่ เร็ว, เสถียร, และรองรับข้อมูลขนาดใหญ่ ได้ดี มีฟีเจอร์เด็ด ๆ อย่าง JSONB, Indexing, Full-text search และอื่น ๆ อีกเพียบ! 💾

ในบทความนี้ เราจะมาดูกันว่า จะเชื่อมต่อ PostgreSQL กับ Next.js ยังไง ใช้ Prisma, pg, หรือ Drizzle อันไหนเหมาะกับงานแบบไหน และทำยังไงให้โค้ดอ่านง่ายและดูแลต่อได้ง่าย

🎯 PostgreSQL + Next.js ใช้ทำอะไรได้บ้าง?

ถ้าคุณสร้างเว็บที่ต้องการ บันทึกและดึงข้อมูล จากฐานข้อมูล เช่น

✅ เว็บบล็อก → บันทึกและเรียกดูบทความ
✅ เว็บร้านค้า → จัดเก็บสินค้าและคำสั่งซื้อ
✅ ระบบล็อกอิน → เก็บข้อมูลผู้ใช้และการยืนยันตัวตน
✅ เว็บแอปที่ต้องใช้ข้อมูลจริง → เช่น Dashboard, CRM, หรือระบบจอง

การใช้ PostgreSQL เป็นทางเลือกที่ดี เพราะมันรองรับ โครงสร้างข้อมูลที่ซับซ้อน และ ขยายขนาดได้ง่าย 🚀

🛠 วิธีเชื่อมต่อ PostgreSQL กับ Next.js

การเชื่อมต่อ PostgreSQL กับ Next.js ทำได้หลายวิธี เช่น

วิธี ใช้เมื่อ ตัวอย่างเครื่องมือ
ใช้ Prisma ต้องการ ORM ที่ใช้งานง่ายและโค้ดอ่านสวย Prisma
ใช้ pg (node-postgres) ต้องการทำงานกับ SQL โดยตรง pg (node-postgres)
ใช้ Drizzle ORM ต้องการ ORM ที่เบาและเร็ว Drizzle
ใช้ Direct SQL (raw queries) ต้องการประสิทธิภาพสูงสุด SQL Queries ตรง ๆ

🔹 1. เชื่อมต่อ PostgreSQL ด้วย Prisma (ง่ายสุด!)

Prisma เป็น ORM ที่ได้รับความนิยมมาก เพราะมันช่วยให้เราสามารถเขียนโค้ด TypeScript ที่อ่านง่าย และลดปัญหาการจัดการฐานข้อมูล

🏗 ติดตั้ง Prisma และ PostgreSQL Client

npm install @prisma/client @prisma/cli pg

📝 ตั้งค่า .env ให้เชื่อมต่อ PostgreSQL

DATABASE_URL=postgresql://username:password@localhost:5432/mydatabase

🛠 ตั้งค่า Prisma Schema

สร้างไฟล์ prisma/schema.prisma

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

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

🚀 สร้างตารางใน Database

npx prisma migrate dev --name init

📌 ใช้ Prisma ใน API Routes (/pages/api/users.js)

import { PrismaClient } from '@prisma/client'

const prisma = new PrismaClient()

export default async function handler(req, res) {
  if (req.method === 'GET') {
    const users = await prisma.user.findMany()
    res.json(users)
  } else if (req.method === 'POST') {
    const { name, email } = req.body
    const newUser = await prisma.user.create({
      data: { name, email }
    })
    res.json(newUser)
  }
}

✅ ทำไมต้องใช้ Prisma?

✔ ใช้ง่ายและอ่านง่าย
✔ มี Type Safety (ใช้กับ TypeScript ได้ดี)
✔ จัดการ Database Migrations ได้สะดวก

🔹 2. เชื่อมต่อ PostgreSQL ด้วย pg (ทำงานกับ SQL ตรง ๆ)

ถ้าคุณต้องการ เขียน SQL เองโดยตรง และต้องการความยืดหยุ่นสูง pg (node-postgres) เป็นตัวเลือกที่ดี

🏗 ติดตั้ง pg

npm install pg

📝 เชื่อมต่อ PostgreSQL (lib/db.js)

import { Pool } from 'pg'

const pool = new Pool({
  connectionString: process.env.DATABASE_URL,
})

export async function query(text, params) {
  const res = await pool.query(text, params)
  return res.rows
}

📌 ใช้ pg ใน API Routes (/pages/api/users.js)

import { query } from '../../lib/db'

export default async function handler(req, res) {
  if (req.method === 'GET') {
    const users = await query('SELECT * FROM users', [])
    res.json(users)
  } else if (req.method === 'POST') {
    const { name, email } = req.body
    const newUser = await query(
      'INSERT INTO users (name, email) VALUES ($1, $2) RETURNING *',
      [name, email]
    )
    res.json(newUser)
  }
}

✅ ทำไมต้องใช้ pg?

✔ ควบคุม SQL Query ได้เต็มที่
✔ เบาและเร็วกว่า ORM
✔ รองรับ Transactions และ Connection Pooling


🔹 3. ใช้ Drizzle ORM (ทางเลือกใหม่ เบาและเร็ว!)

ถ้าคุณต้องการ ORM ที่ เบาและเร็วกว่า Prisma Drizzle ORM เป็นตัวเลือกที่น่าสนใจ

🏗 ติดตั้ง Drizzle ORM

npm install drizzle-orm pg

📝 สร้าง Connection (lib/db.ts)

import { drizzle } from 'drizzle-orm/node-postgres'
import { Pool } from 'pg'

const pool = new Pool({
  connectionString: process.env.DATABASE_URL,
})

export const db = drizzle(pool)

📌 ใช้ Drizzle ใน API Routes (/pages/api/users.ts)

import { db } from '../../lib/db'

export default async function handler(req, res) {
  if (req.method === 'GET') {
    const users = await db.select().from('users')
    res.json(users)
  }
}

✅ ทำไมต้องใช้ Drizzle?

✔ เร็วกว่า Prisma
✔ ใช้ TypeScript ได้ดี
✔ อ่านง่ายและไม่ต้องใช้ Migrations ใหญ่ ๆ

🎯 สรุป

วิธี ใช้เมื่อ เครื่องมือที่ใช้
Prisma ต้องการ ORM ที่ใช้งานง่าย Prisma
pg (node-postgres) ต้องการเขียน SQL เอง pg
Drizzle ORM ต้องการ ORM ที่เบาและเร็ว Drizzle


🔹 ถ้าคุณ ชอบ ORM และอยากให้โค้ดดูสวย ๆ → ใช้ Prisma
🔹 ถ้าคุณ ต้องการความเร็วและควบคุม SQL เอง → ใช้ pg
🔹 ถ้าคุณ อยากได้ ORM ที่เบาและเร็วกว่า Prisma → ใช้ Drizzle

วันพุธที่ 5 มีนาคม พ.ศ. 2568

การแคชข้อมูลใน Next.js: โหลดเร็ว ประหยัดทรัพยากร ทำยังไง?

ถ้าอยากให้เว็บโหลดเร็ว แคช (Cache) คือสิ่งที่ต้องรู้! แคชช่วยลดการเรียก API ซ้ำ ๆ ประหยัดเวลา ประหยัดเซิร์ฟเวอร์ และทำให้ผู้ใช้รู้สึกว่าเว็บเร็วขึ้นมาก 🚀

ใน Next.js เรามีหลายวิธีในการแคชข้อมูล ตั้งแต่ Static Generation (SSG), Server-side Rendering (SSR), Client-side caching (SWR) ไปจนถึง Edge Caching วันนี้เราจะมาดูกันว่าแต่ละแบบใช้เมื่อไหร่ และทำให้เว็บเร็วขึ้นได้ยังไง!

🔥 ทำไมต้องแคชข้อมูล?

ลองนึกภาพว่าเว็บของคุณต้องโหลด สินค้าล่าสุด จาก API ทุกครั้งที่มีคนเข้าเว็บ … 🤯

  • ถ้าคนเข้า 100 คน = API ถูกเรียก 100 ครั้ง
  • ถ้า API ช้า? เว็บช้าไปด้วย
  • ถ้า API มีค่าใช้จ่าย? ยิ่งแพงขึ้นเรื่อย ๆ

แต่ถ้าเราสามารถเก็บข้อมูลไว้ชั่วคราว ไม่ต้องเรียก API ตลอดเวลา เว็บจะเร็วขึ้น ประหยัดทรัพยากร และลดโหลดเซิร์ฟเวอร์

🛠 วิธีการแคชใน Next.js

Next.js รองรับการแคชหลายแบบขึ้นอยู่กับว่า ข้อมูลของคุณเปลี่ยนบ่อยแค่ไหน

วิธีแคช ใช้เมื่อ ตัวอย่าง
Static Generation (SSG) ข้อมูลไม่ค่อยเปลี่ยน หน้า About, รายการสินค้า
Incremental Static Regeneration (ISR) ข้อมูลเปลี่ยนเป็นช่วง ๆ บทความข่าว, ราคา Bitcoin
Server-side Rendering (SSR) ข้อมูลต้องสดใหม่ทุกครั้ง ข้อมูลผู้ใช้, หน้าแดชบอร์ด
Client-side Fetching (SWR, React Query) ข้อมูลเปลี่ยนบ่อยแบบเรียลไทม์ Notification, Dashboard
Edge Caching ต้องการโหลดเร็วสุด ๆ Content ที่แจกจ่ายไปทั่วโลก (CDN)


🏗 1. แคชข้อมูลด้วย Static Generation (SSG)

ถ้าข้อมูลไม่เปลี่ยนบ่อย SSG เป็นวิธีที่ดีที่สุด เพราะ Next.js จะ ดึงข้อมูลมาตอน Build แล้วเสิร์ฟเป็นไฟล์ HTML ทำให้โหลดเร็วสุด ๆ

🔹 ตัวอย่าง SSG

export async function getStaticProps() {
  const res = await fetch('https://api.example.com/products')
  const products = await res.json()

  return { props: { products } }
}

export default function ProductsPage({ products }) {
  return (
    <ul>
      {products.map((product) => (
        <li key={product.id}>{product.name}</li>
      ))}
    </ul>
  )
}

✅ ข้อดีของ SSG

  • โหลดเร็วมาก เพราะเป็นไฟล์ HTML ธรรมดา
  • ลดโหลดเซิร์ฟเวอร์
  • เหมาะกับข้อมูลที่ไม่เปลี่ยนบ่อย เช่น บทความ หรือ รายการสินค้า

❌ ข้อเสีย

  • ถ้าข้อมูลเปลี่ยน จะไม่อัปเดตจนกว่าจะ Build ใหม่


🔄 2. อัปเดต Static Page ด้วย ISR (Incremental Static Regeneration)

ถ้าอยากใช้ SSG แต่ให้ข้อมูลอัปเดตเป็นช่วง ๆ เราสามารถใช้ revalidate เพื่อให้ Next.js รีเฟรชข้อมูลอัตโนมัติ

🔹 ตัวอย่าง ISR (รีเฟรชข้อมูลทุก 60 วินาที)

export async function getStaticProps() {
  const res = await fetch('https://api.example.com/news')
  const news = await res.json()

  return { props: { news }, revalidate: 60 } // รีเฟรชทุก 60 วินาที
}

✅ ข้อดีของ ISR

  • โหลดเร็วเหมือน SSG
  • ข้อมูลอัปเดตได้เอง ไม่ต้อง Deploy ใหม่


⚡ 3. โหลดข้อมูลฝั่งเซิร์ฟเวอร์ (SSR)

ถ้าข้อมูลต้องอัปเดตทุกครั้งที่มีคนเข้าหน้า SSR (Server-side Rendering) คือทางเลือกที่ดี

🔹 ตัวอย่าง SSR

export async function getServerSideProps() {
  const res = await fetch('https://api.example.com/user')
  const user = await res.json()

  return { props: { user } }
}

✅ ข้อดีของ SSR

  • ข้อมูลสดใหม่เสมอ
  • เหมาะกับข้อมูลผู้ใช้ หรือแดชบอร์ด

❌ ข้อเสีย

  • ช้ากว่า SSG และ ISR เพราะต้องรอโหลดทุกครั้ง


🌀 4. แคชข้อมูลฝั่ง Client ด้วย SWR

ถ้าต้องการให้ข้อมูล อัปเดตอัตโนมัติแบบเรียลไทม์ ใช้ SWR (Stale-While-Revalidate) เป็นตัวเลือกที่ดี

🔹 ตัวอย่างการใช้ SWR

import useSWR from 'swr'

const fetcher = (url) => fetch(url).then(res => res.json())

export default function Dashboard() {
  const { data, error } = useSWR('/api/dashboard', fetcher, { refreshInterval: 5000 })

  if (error) return <p>เกิดข้อผิดพลาด</p>
  if (!data) return <p>กำลังโหลด...</p>

  return <div>จำนวนผู้ใช้ตอนนี้: {data.users}</div>
}

✅ ข้อดีของ SWR

  • โหลดเร็วเพราะดึงจากแคชก่อน
  • อัปเดตข้อมูลอัตโนมัติ

❌ ข้อเสีย

  • ใช้ได้เฉพาะฝั่ง Client


🌍 5. ใช้ Edge Caching เพื่อโหลดเร็วสุด ๆ

ถ้าอยากให้ Response ถูกแคชทั่วโลก (CDN) Next.js มีฟีเจอร์ Middleware + Edge Functions

🔹 ตัวอย่าง Middleware Caching

import { NextResponse } from 'next/server'

export function middleware(req) {
  const response = NextResponse.next()
  response.headers.set('Cache-Control', 's-maxage=60, stale-while-revalidate')
  return response
}

✅ เหมาะกับ

  •     โหลดเร็วสุด ๆ สำหรับ Static Content
  •     ใช้ร่วมกับ CDN เช่น Vercel, Cloudflare


🔥 สรุป: ควรใช้แคชแบบไหน?

วิธีแคช ใช้เมื่อ
SSG ข้อมูลไม่เปลี่ยนบ่อย (โหลดเร็วมาก)
ISR ข้อมูลเปลี่ยนเป็นช่วง ๆ (อัปเดตอัตโนมัติ)
SSR ข้อมูลต้องสดใหม่ทุกครั้ง
SWR อัปเดตข้อมูลอัตโนมัติฝั่ง Client
Edge Caching โหลดเร็วสุด ๆ ทั่วโลก

✅ ใช้ SSG หรือ ISR ถ้าเป็นไปได้ เพราะเร็วและลดโหลดเซิร์ฟเวอร์
✅ ใช้ SSR เมื่อข้อมูลต้องอัปเดตเสมอ
✅ ใช้ SWR ถ้าเป็นข้อมูลที่ต้องอัปเดตเรียลไทม์

วันอังคารที่ 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 คือสิ่งที่คุณต้องใช้! 🚀

วันจันทร์ที่ 3 มีนาคม พ.ศ. 2568

การเรียก API ภายใน Next.js อย่างมีประสิทธิภาพ

การเรียก API เป็นเรื่องที่ทุกเว็บแอปต้องทำ ไม่ว่าจะเป็นการดึงข้อมูลจาก Backend, Third-party APIs หรือแม้แต่ API ภายในแอปเอง แต่จะเรียกยังไงให้เร็ว แรง และไม่ทำให้เว็บช้า?

Next.js มีหลายวิธีในการเรียก API ไม่ว่าจะเป็น Server-side fetching, Client-side fetching, Static generation, หรือแม้แต่ ใช้ API Routes ภายในตัวเอง วันนี้เราจะมาเจาะลึกกันว่าควรเลือกใช้วิธีไหนในแต่ละสถานการณ์ เพื่อให้แอปของคุณทำงานเร็วที่สุด 🚀

🔍 วิธีเรียก API ใน Next.js

ใน Next.js เราสามารถเรียก API ได้หลัก ๆ 3 วิธี

  1. Client-side fetching → ใช้ fetch หรือ SWR ใน React Component
  2. Server-side fetching (SSR) → ใช้ getServerSideProps เพื่อโหลดข้อมูลตอนโหลดหน้า
  3. Static generation (SSG) → ใช้ getStaticProps โหลดข้อมูลล่วงหน้า

แต่ละวิธีมีข้อดีข้อเสียต่างกัน เดี๋ยวมาดูรายละเอียดกันเลย!

🎯 1. การเรียก API ฝั่ง Client (Client-side Fetching)

ถ้าข้อมูลที่เราต้องการโหลด ไม่จำเป็นต้องมาเร็วก่อนหน้าแสดงผล เช่น

  •     รายการโพสต์
  •     คอมเมนต์
  •     ข้อมูลที่อัปเดตแบบเรียลไทม์

การใช้ Client-side Fetching จะช่วยให้หน้าเว็บโหลดเร็วขึ้นเพราะมันจะดึงข้อมูลหลังจากโหลดหน้าเสร็จ

🔹 วิธีใช้ fetch กับ useEffect (พื้นฐาน)

import { useEffect, useState } from 'react'

export default function Posts() {
  const [posts, setPosts] = useState([])
  const [loading, setLoading] = useState(true)

  useEffect(() => {
    fetch('/api/posts')
      .then((res) => res.json())
      .then((data) => {
        setPosts(data)
        setLoading(false)
      })
  }, [])

  if (loading) return <p>กำลังโหลดโพสต์...</p>

  return (
    <ul>
      {posts.map((post) => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  )
}

แต่ปัญหาของวิธีนี้คือ ทุกครั้งที่เข้าเพจ มันจะ fetch API ใหม่เสมอ ซึ่งอาจทำให้โหลดข้อมูลซ้ำ ๆ แบบไม่จำเป็น

🔹 วิธีใช้ SWR ให้โหลดเร็วขึ้น

ถ้าอยากให้ ดึงข้อมูลแล้วแคชไว้ ไม่ต้องโหลดใหม่ตลอด SWR เป็นตัวช่วยที่ดี

import useSWR from 'swr'

const fetcher = (url) => fetch(url).then((res) => res.json())

export default function Posts() {
  const { data, error } = useSWR('/api/posts', fetcher)

  if (error) return <p>เกิดข้อผิดพลาด</p>
  if (!data) return <p>กำลังโหลด...</p>

  return (
    <ul>
      {data.map((post) => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  )
}

✅ SWR ดียังไง?

  •     แคชข้อมูลไว้ ไม่ต้องโหลดใหม่ทุกครั้ง
  •     อัปเดตข้อมูลอัตโนมัติเมื่อมีการเปลี่ยนแปลง
  •     โหลดเร็วขึ้นเพราะดึงจากแคชก่อน แล้วอัปเดตภายหลัง

ถ้าเป็น ข้อมูลที่ต้องอัปเดตบ่อย เช่น Dashboard หรือ Notifications ควรใช้ SWR จะดีที่สุด!

⚡️ 2. การเรียก API ฝั่งเซิร์ฟเวอร์ (SSR)

บางครั้งเราต้องโหลดข้อมูล ก่อนแสดงผลหน้าเว็บ เช่น

  • ข้อมูลผู้ใช้ที่ล็อกอิน
  • สินค้าในตะกร้า
  • รายการสั่งซื้อ

ในกรณีนี้ getServerSideProps เป็นทางเลือกที่ดี เพราะมันจะดึงข้อมูลบนเซิร์ฟเวอร์ก่อนแล้วส่งไปให้หน้าเว็บ

🔹 วิธีใช้ getServerSideProps

export async function getServerSideProps() {
  const res = await fetch('https://jsonplaceholder.typicode.com/posts')
  const data = await res.json()

  return { props: { posts: data } }
}

export default function Posts({ posts }) {
  return (
    <ul>
      {posts.map((post) => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  )
}

✅ ข้อดีของ SSR

  • โหลดข้อมูลก่อนแสดงผล → ผู้ใช้เห็นข้อมูลทันที
  • เหมาะกับข้อมูลที่เปลี่ยนแปลงบ่อย เช่น ข้อมูลผู้ใช้
  • รองรับ SEO ดีกว่า Client-side Fetching

❌ ข้อเสีย

  • โหลดช้ากว่าเพราะต้องรอ API ตอบก่อนแสดงผล
  • ถ้า API ช้าจะทำให้หน้าเว็บช้าไปด้วย

ถ้าเป็น API ที่ต้องใช้ข้อมูลสดใหม่ทุกครั้ง เช่น ข้อมูลผู้ใช้ที่ล็อกอินอยู่ getServerSideProps คือทางเลือกที่ดี

🏎 3. โหลด API ล่วงหน้าด้วย Static Generation (SSG)

ถ้าข้อมูลที่เราต้องการ เปลี่ยนแปลงไม่บ่อย เช่น

  • บทความ
  • รายชื่อสินค้า
  • รายการหมวดหมู่

เราสามารถใช้ getStaticProps โหลดข้อมูลตอน Build เวลา Deploy แล้วหน้าเว็บจะโหลดเร็วมาก 🚀

🔹 วิธีใช้ getStaticProps

export async function getStaticProps() {
  const res = await fetch('https://jsonplaceholder.typicode.com/posts')
  const data = await res.json()

  return { props: { posts: data } }
}

export default function Posts({ posts }) {
  return (
    <ul>
      {posts.map((post) => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  )
}

✅ ข้อดีของ SSG

  • โหลดเร็วมาก เพราะไม่ต้องรอ API ตอนเปิดหน้า
  • เหมาะกับหน้าเว็บที่ข้อมูลเปลี่ยนไม่บ่อย

❌ ข้อเสีย

  • ข้อมูลจะไม่อัปเดตจนกว่าจะ Build ใหม่

ถ้าต้องการให้ SSG รีเฟรชข้อมูลได้เอง สามารถใช้ revalidate เช่น

export async function getStaticProps() {
  const res = await fetch('https://jsonplaceholder.typicode.com/posts')
  const data = await res.json()

  return { props: { posts: data }, revalidate: 60 } // รีเฟรชทุก 60 วินาที
}

🔥 สรุป: ควรใช้วิธีไหน?

วิธี ใช้เมื่อ ข้อดี ข้อเสีย
Client-side Fetching ข้อมูลเปลี่ยนบ่อย (Dashboard, คอมเมนต์) โหลดเร็ว ไม่ต้องรอ API ไม่ดีต่อ SEO
Server-side Fetching (SSR) ข้อมูลต้องอัปเดตทุกครั้ง เช่น ผู้ใช้ล็อกอิน โหลดก่อนแสดงผล ดีต่อ SEO ช้ากว่า Client-side
Static Generation (SSG) ข้อมูลเปลี่ยนไม่บ่อย เช่น บทความ โหลดเร็วมาก ไม่อัปเดตอัตโนมัติ

เลือกให้เหมาะสมกับโปรเจกต์ของคุณ แล้วเว็บจะทั้งเร็วและมีประสิทธิภาพ! 🚀

วันอาทิตย์ที่ 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 ดู แล้วจะรู้ว่ามัน โคตรสะดวก! 🚀

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

การใช้ SWR ใน Next.js เพื่อดึงข้อมูลแบบ Client-side

ในโลกของการพัฒนาเว็บแอปพลิเคชัน ฝั่ง Frontend ต้องมีวิธีดึงข้อมูลจาก API อย่างมีประสิทธิภาพ ซึ่งใน Next.js มีหลายแนวทางให้เลือกใช้ เช่น getServerSideProps (SSR), getStaticProps (SSG), หรือ Client-side Fetching ซึ่งแต่ละวิธีก็มีข้อดีข้อเสียต่างกันไป

ถ้าพูดถึงการดึงข้อมูลแบบ Client-side แล้ว SWR เป็นตัวเลือกที่หลายคนชอบ เพราะมันช่วยให้การ fetch ข้อมูลลื่นไหล อัปเดตอัตโนมัติ และยังจัดการแคชได้อย่างฉลาด วันนี้เราจะมาทำความรู้จัก SWR และดูวิธีใช้งานใน Next.js กันแบบเข้าใจง่าย ๆ

🔍 SWR คืออะไร?

SWR ย่อมาจาก Stale-While-Revalidate เป็นแนวคิดที่ช่วยให้การดึงข้อมูลเร็วและสดใหม่ตลอดเวลา โดยที่ไม่ต้องให้ผู้ใช้รอนานเกินไป โดยถูกพัฒนาโดยทีมเดียวกับ Next.js (Vercel) ทำให้มันเหมาะกับการใช้ในโปรเจ็กต์ที่พัฒนาโดย Next.js มาก

หลักการของ SWR คือ

  • คืนค่าข้อมูลเก่าจากแคชก่อน เพื่อให้ผู้ใช้เห็นข้อมูลเร็วที่สุด
  • ดึงข้อมูลใหม่จาก API อยู่เบื้องหลัง
  • อัปเดตข้อมูลใหม่ ใน UI อัตโนมัติ

ฟังดูดีใช่ไหม? เพราะมันช่วยให้การโหลดข้อมูลไม่กระตุก และมีประสบการณ์ใช้งานที่ดีขึ้น

🚀 ติดตั้ง SWR

ก่อนอื่น ถ้ายังไม่ได้ติดตั้ง SWR สามารถติดตั้งได้ง่าย ๆ ด้วยคำสั่งนี้

npm install swr
# หรือถ้าใช้ yarn
yarn add swr

เสร็จแล้วก็พร้อมลุย! 🎉

🛠 วิธีใช้ SWR เบื้องต้น

SWR ใช้งานง่ายมาก ๆ เพียงแค่ import และใช้ useSWR ใน React Component

import useSWR from 'swr'

const fetcher = (url) => fetch(url).then(res => res.json())

export default function Profile() {
  const { data, error } = useSWR('/api/user', fetcher)

  if (error) return <div>โหลดข้อมูลไม่สำเร็จ 😢</div>
  if (!data) return <div>กำลังโหลดข้อมูล... ⏳</div>

  return (
    <div>
      <h1>สวัสดี, {data.name}!</h1>
      <p>อีเมล: {data.email}</p>
    </div>
  )
}

อธิบายโค้ด

  • เราใช้ useSWR เพื่อดึงข้อมูลจาก /api/user
  • fetcher คือฟังก์ชันที่ใช้ดึงข้อมูลจาก API
  • ถ้ามี error จะแสดงข้อความผิดพลาด
  • ถ้าข้อมูลยังมาไม่ถึง จะแสดงข้อความ กำลังโหลด...
  • ถ้าทุกอย่างเรียบร้อยแล้ว ก็โชว์ข้อมูลที่ดึงมาได้

ข้อดีของวิธีนี้คือ ไม่ต้องใช้ useEffect หรือจัดการ state เองเลย เพราะ SWR จัดการให้หมด!

⚡️ ทำไม SWR ถึงดีกว่า useEffect + fetch?

บางคนอาจสงสัยว่า "แล้วทำไมไม่ใช้ useEffect กับ fetch ตรง ๆ ล่ะ?" คำตอบคือ SWR ดีกว่าเพราะ

✅ จัดการแคชให้อัตโนมัติ – ไม่ต้องโหลดข้อมูลซ้ำถ้ายังอยู่ในแคช
✅ อัปเดตข้อมูลเมื่อมีการเปลี่ยนแปลง – ไม่ต้อง reload หน้าเอง
✅ รองรับการ Revalidate อัตโนมัติ – ดึงข้อมูลใหม่เมื่อลูกค้ากลับมาที่หน้าเว็บ
✅ รองรับการดึงข้อมูลแบบ on-focus & re-fetch on reconnect – ไม่ต้องกดรีเฟรชเอง

ถ้าใช้ useEffect และ fetch เราต้องเขียนโค้ดจัดการแคชเอง ซึ่งยุ่งยากและซับซ้อนกว่า

🔄 ตัวอย่างการใช้ Mutate และ Revalidate

ถ้าต้องการให้ข้อมูลอัปเดตทันทีโดยไม่ต้องรอ SWR รีเฟรชเอง สามารถใช้ mutate ได้

import useSWR, { mutate } from 'swr'

const fetcher = (url) => fetch(url).then(res => res.json())

export default function Dashboard() {
  const { data } = useSWR('/api/stats', fetcher)

  return (
    <div>
      <h1>ยอดผู้ใช้งาน: {data ? data.users : 'กำลังโหลด...'}</h1>
      <button onClick={() => mutate('/api/stats')}>โหลดข้อมูลใหม่</button>
    </div>
  )
}

เมื่อกดปุ่ม โหลดข้อมูลใหม่ ระบบจะดึงข้อมูลใหม่จาก API ทันที

🔐 ใช้ SWR กับ Authentication

SWR เหมาะกับระบบที่ต้องใช้ Token Authentication เช่น JWT หรือ OAuth เพราะสามารถส่ง Header ไปกับทุก Request ได้ง่าย ๆ

import useSWR from 'swr'

const fetcher = (url) =>
  fetch(url, {
    headers: {
      Authorization: `Bearer ${localStorage.getItem('token')}`,
    },
  }).then((res) => res.json())

export default function UserProfile() {
  const { data, error } = useSWR('/api/profile', fetcher)

  if (error) return <div>โหลดข้อมูลไม่สำเร็จ</div>
  if (!data) return <div>กำลังโหลด...</div>

  return <h1>ชื่อผู้ใช้: {data.username}</h1>
}


🔥 การใช้งาน SWR กับ GraphQL

ถ้าใช้ GraphQL เราก็สามารถใช้ SWR ได้ โดยเปลี่ยนจาก fetch เป็นการส่ง Query ไปยัง API

const fetcher = (query) =>
  fetch('/graphql', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ query }),
  }).then((res) => res.json())

const GET_USER = `
  {
    user {
      name
      email
    }
  }
`

export default function UserProfile() {
  const { data, error } = useSWR(GET_USER, fetcher)

  if (error) return <div>โหลดข้อมูลไม่สำเร็จ</div>
  if (!data) return <div>กำลังโหลด...</div>

  return <h1>ชื่อ: {data.user.name}</h1>
}

📌 สรุป

SWR เป็นเครื่องมือที่ช่วยให้การดึงข้อมูลแบบ Client-side ง่ายขึ้น โดยที่ไม่ต้องจัดการแคชเอง รองรับการอัปเดตข้อมูลอัตโนมัติ และมีประสิทธิภาพสูงกว่าการใช้ useEffect + fetch แบบเดิม ๆ
✅ เหมาะกับ

  • ดึงข้อมูลที่เปลี่ยนแปลงบ่อย เช่น ยอดไลก์, คอมเมนต์, จำนวนผู้ใช้
  • แสดงข้อมูลให้ผู้ใช้เร็วที่สุด โดยใช้แคช
  • อัปเดตข้อมูลอัตโนมัติ โดยไม่ต้องรีเฟรชหน้า

ถ้าคุณใช้ Next.js อยู่แล้ว ลองเอา SWR ไปใช้ดู รับรองว่าชีวิตง่ายขึ้นแน่นอน! 🚀

วันเสาร์ที่ 15 กุมภาพันธ์ พ.ศ. 2568

Next.js คืออะไร และทำไมต้องใช้ Next.js

    ถ้าพูดถึงการพัฒนาเว็บแอปพลิเคชันด้วย React.js หลายคนน่าจะเคยได้ยินชื่อ Next.js มาบ้าง แต่บางคนอาจจะยังไม่แน่ใจว่ามันคืออะไร ดียังไง และทำไมเราถึงควรใช้มัน แทนที่จะใช้ React ธรรมดา วันนี้เราจะมาทำความรู้จักกับ Next.js กันแบบเข้าใจง่าย ๆ กันเลย!

Next.js คืออะไร?

    Next.js เป็นเฟรมเวิร์กที่ถูกสร้างขึ้นมาบน React ซึ่งช่วยให้การพัฒนาเว็บแอปเป็นเรื่องง่ายขึ้น โดยเฉพาะในเรื่องของการทำงานฝั่งเซิร์ฟเวอร์ (Server-side Rendering) และการทำ SEO ซึ่งเป็นจุดที่ React ปกติทำได้ยาก

    ถ้าเปรียบเทียบง่าย ๆ React ก็เหมือนกับชิ้นส่วนต่าง ๆ ของรถยนต์ ส่วน Next.js คือรถยนต์ที่ประกอบเสร็จแล้ว มีเครื่องยนต์พร้อมขับ แค่เติมน้ำมัน (โค้ด) ก็ใช้งานได้เลย! ไม่ต้องมาประกอบเองให้วุ่นวาย

ทำไมต้องใช้ Next.js?

    1. โหลดเร็วกว่า ด้วย Server-side Rendering (SSR) และ Static Site Generation (SSG) ปกติแล้ว React ใช้วิธี Client-side Rendering (CSR) คือโหลดหน้าเว็บมาก่อน แล้วไปดึงข้อมูลจาก API มาเติมทีหลัง ทำให้บางครั้งหน้าเว็บโหลดมาแล้ว แต่ยังไม่มีข้อมูล ต้องรออีกแป๊บนึงถึงจะแสดงผลครบ ซึ่งไม่ดีต่อ SEO และ UX เลย

แต่ Next.js แก้ปัญหานี้ด้วย SSR และ SSG

  • SSR (Server-side Rendering): ดึงข้อมูลจากเซิร์ฟเวอร์ก่อน แล้วส่งหน้าเว็บที่มีข้อมูลพร้อมให้ผู้ใช้ทันที โหลดเร็วขึ้นเยอะ!
  • SSG (Static Site Generation): สร้างหน้าเว็บเป็นไฟล์ HTML ตั้งแต่ตอน Build แล้วโหลดแบบ Static ทำให้เว็บเร็วสุด ๆ แถมยังลดภาระเซิร์ฟเวอร์อีกด้วย

    2. SEO ดีขึ้น เพราะ Google อ่านเนื้อหาได้เลย หนึ่งในปัญหาใหญ่ของ React คือ Google Bot ไม่สามารถอ่านเนื้อหาบนเว็บที่ใช้ CSR ได้ดีนัก เพราะทุกอย่างโหลดผ่าน JavaScript แต่ถ้าใช้ Next.js ที่รองรับ SSR และ SSG ก็จะช่วยให้ Google มองเห็นเนื้อหาได้ง่ายขึ้น ส่งผลให้ SEO ของเราดีขึ้นแบบเห็นได้ชัด

    3. มีระบบ Routing อัตโนมัติ (File-based Routing) ปกติถ้าใช้ React อย่างเดียว เราต้องใช้ React Router มาจัดการเส้นทาง (Routes) เอง แต่ใน Next.js แค่สร้างไฟล์ในโฟลเดอร์ pages/ เช่น:

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


แค่สร้างไฟล์ก็ได้ Routing อัตโนมัติ ไม่ต้อง config เองให้ยุ่งยาก

    4. API Routes - ทำ Backend ได้ในตัว Next.js ไม่ได้มีดีแค่ Frontend แต่ยังให้เราสร้าง API ได้เลยในโฟลเดอร์ pages/api/ เช่น:

  • pages/api/hello.js → GET /api/hello

    ซึ่งเราสามารถใช้ API นี้เชื่อมต่อกับฐานข้อมูล หรือใช้ร่วมกับ Frontend ได้ทันที ไม่ต้องไปเปิดเซิร์ฟเวอร์แยก

    5. รองรับ Image Optimization อัตโนมัติ Next.js มีฟีเจอร์ next/image ที่ช่วยให้เราจัดการภาพได้ง่ายขึ้น ไม่ต้องมานั่ง Optimize เอง เช่น การปรับขนาดอัตโนมัติ การแปลงเป็น WebP และการโหลดแบบ Lazy Loading เพื่อช่วยให้เว็บโหลดเร็วขึ้น

    6. รองรับการ Deploy ง่าย ๆ บน Vercel Next.js ถูกสร้างโดยทีมงานของ Vercel ซึ่งเป็นแพลตฟอร์มสำหรับ Deploy เว็บแบบ Serverless เราสามารถเชื่อม GitHub หรือ GitLab แล้วกด Deploy ได้ในไม่กี่คลิก แถมมีฟีเจอร์ CI/CD ให้ใช้งานด้วย

    7. รองรับการใช้งานกับ Tailwind CSS ได้อย่างง่ายดาย ถ้าใครชอบใช้ Tailwind CSS ก็สามารถติดตั้งกับ Next.js ได้ง่าย ๆ และใช้งานร่วมกันได้อย่างสมบูรณ์แบบ ทำให้การเขียน UI เร็วขึ้นมาก

Next.js เหมาะกับใคร?

    Next.js เหมาะกับนักพัฒนาเว็บที่ต้องการ พัฒนาเว็บให้เร็วขึ้น ทำ SEO ให้ดีขึ้น และลดความซับซ้อนของโปรเจกต์ ไม่ว่าจะเป็น

  • เว็บทั่วไปที่ต้องการ SEO เช่น บล็อก หรือเว็บข่าว
  • เว็บอีคอมเมิร์ซ ที่ต้องโหลดข้อมูลเร็วและรองรับ SEO
  • Dashboard หรือแอปพลิเคชันที่ใช้ข้อมูลเยอะ ๆ
  • SaaS หรือเว็บ Subscription ที่ต้องการประสิทธิภาพสูง
  • เว็บที่ต้องการ Full-stack API ในตัว ไม่ต้องเปิดเซิร์ฟเวอร์แยก


ข้อเสียของ Next.js ที่ควรรู้

    แน่นอนว่าไม่มีอะไรสมบูรณ์แบบ Next.js ก็มีข้อจำกัดบางอย่าง เช่น

  • เรียนรู้เพิ่มขึ้นจาก React ปกติ เพราะมี SSR, SSG, ISR ที่ต้องเข้าใจเพิ่ม
  • SSR อาจจะช้ากว่า CSR ถ้าต้องดึงข้อมูลเยอะมาก เพราะเซิร์ฟเวอร์ต้อง Generate หน้าใหม่ทุกครั้ง
  • Hosting อาจต้องใช้แพลตฟอร์มเฉพาะ เช่น Vercel หรือโฮสต์ที่รองรับ SSR ไม่ใช่ทุกที่รองรับได้ง่ายเหมือน React ปกติ


สรุป: Next.js ดีไหม? ควรใช้หรือเปล่า?

    ถ้าคุณใช้ React และต้องการเพิ่มประสิทธิภาพให้เว็บ โหลดเร็วขึ้น ทำ SEO ได้ดีขึ้น และมีฟีเจอร์ Backend ในตัว Next.js คือคำตอบ! โดยเฉพาะถ้าคุณพัฒนาเว็บที่เน้นความเร็วและต้องการให้ Google มองเห็นเนื้อหาแบบเต็ม ๆ

    แต่ถ้าโปรเจกต์ของคุณเป็น Single Page Application (SPA) ธรรมดาที่ไม่สน SEO หรือโหลดข้อมูลฝั่งไคลเอนต์เป็นหลัก การใช้ React ปกติอาจจะเหมาะกว่า

แต่ถ้าอยากลอง Next.js ก็ไม่ยาก! สามารถติดตั้งและเริ่มต้นใช้งานได้ง่าย ๆ แค่รันคำสั่งนี้:

npx create-next-app@latest my-next-app
cd my-next-app
npm run dev

แล้วเข้าไปที่ http://localhost:3000 แค่นี้ก็พร้อมใช้งาน Next.js แล้ว!

    นี่คือภาพรวมของ Next.js และเหตุผลว่าทำไมมันถึงเป็นเฟรมเวิร์กที่นักพัฒนาหลายคนชื่นชอบ ถ้าคุณกำลังมองหาเครื่องมือที่จะช่วยให้เว็บของคุณเร็วขึ้นและรองรับ SEO ได้ดีขึ้น Next.js คือตัวเลือกที่ไม่ควรพลาด!

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

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