/Projects
Next.js
ProjectsCS ChallengeFrontendNext.js

หน้าเว็บและ Routing ด้วย Next.js

ใช้ใน Challenge Day 2 และ Day 3

Next.js คือ framework ที่ครอบ React อีกชั้น เพิ่มสิ่งที่เว็บจริงต้องมี: หลายหน้า, SEO, รันโค้ดบนเซิร์ฟเวอร์ได้ และ build ให้เร็ว จุดเด่นคือ file-based routing: สร้างโฟลเดอร์ใน app = ได้หน้าใหม่

At a glance

ItemDetails
ต้องมีNode.js LTS (ดูวิธีติดตั้ง)
สร้างโปรเจกต์npx create-next-app@latest
รันบนเครื่องnpm run dev แล้วเปิด http://localhost:3000
Routingโฟลเดอร์ใน app/ + ไฟล์ page.tsx = 1 หน้า
DeployVercel

Installation

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

    --yes ใช้ค่าแนะนำทั้งหมด: TypeScript, Tailwind CSS, ESLint และ App Router

    npx create-next-app@latest my-portfolio --yes
  2. เปิดโปรเจกต์

    cd my-portfolio
    code .
  3. รันบนเครื่อง

    npm run dev

    เปิด http://localhost:3000 แก้ app/page.tsx แล้วกดเซฟ หน้าเว็บจะเปลี่ยนทันที

Project structure

my-portfolio/
├── app/
│   ├── layout.tsx          ← โครงที่ทุกหน้าใช้ร่วมกัน (navbar, footer, font)
│   ├── page.tsx            ← หน้าแรก  /
│   ├── globals.css
│   ├── about/
│   │   └── page.tsx        ← /about
│   └── projects/
│       ├── page.tsx        ← /projects
│       └── [slug]/
│           └── page.tsx    ← /projects/อะไรก็ได้  (dynamic route)
├── components/             ← component ที่ใช้ซ้ำ
├── public/                 ← รูปและไฟล์ static เช่น /me.jpg
└── package.json
ไฟล์URL ที่ได้
app/page.tsx/
app/about/page.tsx/about
app/projects/page.tsx/projects
app/projects/[slug]/page.tsx/projects/portfolio, /projects/coffee, …
public/me.jpg/me.jpg

layout.tsx ห่อทุกหน้า ใช้ <Link> แทน <a> เพื่อเปลี่ยนหน้าโดยไม่โหลดใหม่

// app/layout.tsx
import Link from "next/link";
import "./globals.css";

export const metadata = { title: "My Portfolio" };

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="th">
      <body>
        <nav>
          <Link href="/">Home</Link>
          <Link href="/about">About</Link>
          <Link href="/projects">Projects</Link>
        </nav>
        {children}  {/* ← หน้าแต่ละหน้ามาแสดงตรงนี้ */}
      </body>
    </html>
  );
}

Dynamic routes

ใส่ชื่อโฟลเดอร์ในวงเล็บเหลี่ยม แล้วอ่านค่าจาก URL ผ่าน params

// app/projects/[slug]/page.tsx
export default async function ProjectPage({
  params,
}: {
  params: Promise<{ slug: string }>;
}) {
  const { slug } = await params;
  return <h1>Project: {slug}</h1>;
}

Server และ Client components

ทุก component ใน app/ เป็น Server Component โดยค่าเริ่มต้น: รันบนเซิร์ฟเวอร์ ดึงข้อมูลได้ตรง ๆ แล้วส่ง HTML มาให้เบราว์เซอร์ ถ้าต้องใช้ useState หรือ onClick ให้ใส่ "use client" ที่บรรทัดแรกของไฟล์

// Server Component: ดึงข้อมูลก่อนส่งหน้าให้ผู้ใช้
export default async function ProductsPage() {
  const res = await fetch("http://localhost:4000/api/products", { cache: "no-store" });
  const products = await res.json();
  return <pre>{JSON.stringify(products, null, 2)}</pre>;
}

คำสั่งหลัก

คำสั่งทำอะไร
npm run devรันเว็บบนเครื่องแบบแก้แล้วเห็นทันที
npm run buildbuild เหมือนตอน deploy (เช็ก error ก่อน push)
npm startรันเวอร์ชันที่ build แล้ว
npm run lintตรวจโค้ดด้วย ESLint
npm install <package>ติดตั้ง library เพิ่ม

ฝึกต่อ

เว็บสำหรับลงมือทำ

วิดีโอเรียนเอง

Next steps

  • Vercel: deploy ให้ได้ลิงก์ของตัวเอง
  • Challenge Day 2: สร้าง portfolio ด้วย Next.js
CS ChallengeLast updated Oct 2026