🛑 1. The Problem First: "Client-Side คือภาระที่หนักอึ้ง"
ลองนึกถึงแอป React แบบเดิม (SPA) ที่ทุุกอย่างเกิดขึ้นบน Browser:
// ❌ สถานการณ์: ลูกค้าต้องแบกรับ JavaScript มหาศาล
// 1. Browser โหลดไฟล์ JS ขนาด 5MB
// 2. Browser รัน JS เพื่อสร้าง HTML (หน้าขาวรอไปก่อน)
// 3. Browser ยิง API ไปดึงข้อมูล (Waterfall)
// 🌋 พัง! กว่าผู้ใช้จะได้เห็นข้อมูลแรก ต้องรอนานถึง 5-10 วินาที
// และ Google Bot ก็มองไม่เห็นเนื้อหาเพราะมันไม่มี HTML ตั้งแต่เริ่มต้น
ปัญหา: การผลักภาระทุุกอย่างไปให้ Browser (Client) ทำงาน คือสาเหตุหลักที่ทำให้เว็บอืดและ SEO พัง Next.js App Router ถูกสร้างขึ้นมาเพื่อ "แย่งงาน" มาทำที่ Server ให้ได้มากที่สุด เพื่อให้ผู้ใช้งานได้รับประสบการณ์ที่ลื่นไหลที่สุดครับ
💡 2. Real-Life Analogy: ร้านอาหารแบบ Fine Dining vs อาหารกล่อง DIY
- Server Components (Default): เหมือน "เชฟที่ทำอาหารเสร็จสรรพใส่จานสวยงามมาเสิร์ฟ". คุณ (Browser) แค่มีหน้าที่กิน (แสดงผล HTML) ไม่ต้องรู้ด้วยซ้ำว่าเชฟหั่นผักหรือปรุงรสยังไง ทุุกอย่างปรุงมาเสร็จแล้ว (Fast & SEO Friendly)
- Client Components ('use client'): เหมือน "ชุดอาหารประกอบเอง (DIY Kit)". เชฟส่งวัตถุดิบและคู่มือมาให้คุณ แล้วคุณต้องออกแรงปรุงเองที่โต๊ะ เหมาะสำหรับงานที่ต้องขยับเขยื้อนบ่อยๆ (Interactive เช่น ปุ่มกด, ช่องกรอกข้อมูล)
- Layouts: เหมือน "โครงสร้างห้างสรรพสินค้า". บันไดเลื่อนและทางเดินยังอยู่ที่เดิมเสมอ แม้คุณจะเดินเข้าร้านนู้นออกร้านนี้ (Navigation) ทำให้ไม่ต้องสร้างทางเดินใหม่ทุุกครั้งที่เปลี่ยนหน้า
🚀 3. Execution Journey: มหากาพย์การใช้ Server First
Senior จะพยายามรักษาโค้ดให้เป็น Server Component ให้ได้มากที่สุด
🛠 Step-by-step:
- The Server Fetch: ดึงข้อมูลด้วย
async/awaitโดยตรงใน Component (ไม่ต้องมีuseEffect!) - The Layout Logic: ใช้
layout.tsxเพื่อเก็บ Navbar/Footer เพื่อลดการประมวลผลซ้ำ - The Interaction Boundary: แยกส่วนที่ต้องมีการคลิก (Click) ออกมาเป็นไฟล์ย่อยแล้วใส่
'use client'ไว้ข้างบนสุด - The Metadata: กำหนด
generateMetadataเพื่อให้แต่ละหน้ามีหัวข้อและรูปแชร์ Social Media ที่ต่างกัน
// ✅ Best Practice: Server Component ดึงข้อมูลตรงจากความแรงของ Server
async function UserPage() {
const users = await fetch("https://api.example.com/users").then((res) =>
res.json(),
);
return (
<div>
<h1>Users List</h1>
<ul>
{users.map((u) => (
<li key={u.id}>{u.name}</li>
))}
</ul>
{/* 🛠 แยกส่วน Interactive ออกไปเป็น Client Component */}
<FollowButton />
</div>
);
}
🪤 4. The Junior Trap: โรค "use client ทุุกไฟล์"
จูเนียร์มักจะใส่ 'use client' ไว้ที่ไฟล์ page.tsx หรือไฟล์หลักเสมอเพราะความเคยชินจาก React:
// ❌ Junior Trap: ผลักภาระกลับไปที่ Client โดยไม่จำเป็น
"use client";
export default function Page() {
const [data, setData] = useState([]); // 🌋 พัง! คุณกำลังทำให้ Next.js กลายเป็น
// React ธรรมดา และทิ้งพลังของการทำ Server-side Rendering (SSR) ไปโดยเปล่าประโยชน์
}
ระวัง: ยิ่งใช้ 'use client' เยอะ JavaScript Bundle ยิ่งบวม
✅ การแก้ไข: จงทำทุุกหน้าให้เป็น Server Component ก่อน แล้วค่อยแทรก Client Component เข้าไปในจุดที่จำเป็นจริงๆ เท่านั้นครับ
⚖️ 5. The Why Matrix: Pages Router vs App Router
| หัวข้อ | Pages Router (แบบเก่า) | App Router ( Senior's Choice) |
|---|---|---|
| Data Fetching | getStaticProps, getServerSideProps | Async/Await (ง่ายกว่าเยอะ!) |
| โครงสร้างไฟล์ | ข้อมูลและหน้าตาผูกติดกัน | Layout/Page (แยกส่วนชัดเจน) |
| ประสิทธิภาพ | ดี แต่ Bundle JS มักจะใหญ่ | 🚀 ดีที่สุด (Bundle เล็กเพราะ Server First) |
| ความง่ายในการเรียนรู้ | ง่ายกว่าเบื้องต้น | 🐢 ยากกว่าในช่วงแรก (ต้องเปลี่ยนวิธีคิด) |
🎓 6. Senior Mindset Summary
การเป็น Senior คือการมองว่า "หน้าเว็บไม่ใช่อะไรที่เราต้องส่ง JavaScript ไปสร้าง แต่คือสิ่งที่ Server ต้องเตรียม HTML ที่สมบูรณ์ที่สุดไปให้". หัวใจของเรื่องนี้ไม่ใช่แค่การใช้เครื่องมือใหม่ แต่มันคือการคืนทรัพยากร (Battery/CPU) ให้กับเครื่องของผู้ใช้งานครับ!