รู้จักกับ Next.js 14 แบบ Quick Overview
/ 6 min read
สามารถดู video ของหัวข้อนี้ก่อนได้ ดู video
Next คืออะไร ?
Next.js คือ React framework ที่สร้างขึ้นมาเพื่อทำ full-stack web application. โจทย์หลักของ Next (ขอเรียกย่อจาก Next.js) คือ
- ใช้ React framework เป็น core หลักในการทำ (สามารถใช้เครื่องมือ debug React ทั้งหมดในการจัดการได้)
- เพิ่มความสามารถจาก Frontend Framework ของ React ให้ทำงานร่วมกับฝั่งของ Server side ได้ (สามารถที่จะ render ข้อมูลก่อนที่จะออกมาที่ Frontend ได้) โดยได้เตรียมของที่จำเป็นสำหรับการจัดการระหว่างฝั่ง Client - Server เอาไว้เรียบร้อย
- Optimization สามารถทำการ optimization code เพื่อให้ได้ Performance สูงสุดของ web ออกมาได้
มาดู Feature หลักๆของ Next กันว่ามีอะไรบ้าง
- Routing = สามารถจัดการ Router ผ่าน file-system based ออกมาได้ (วาง file = ได้ route)
- Rendering = สามารถทำ Client-side and Server-side Rendering with Client and Server Components (รวมถึงการทำ Dynamic rendering ระหว่าง client - server ได้ด้วย)
- Data fetching = สามารถจัดการการดึงข้อมูลผ่าน fetch ได้
- Styling = support หมดทั้ง CSS Module (SASS), Tailwind, CSS-in-JS
- Optimization = build code + asset เพื่อ optimize ผลลัพธ์ที่จะนำไปขึ้น deploy
- Support Typescript
สิ่งที่เราจะมาลองใน Session นี้
Agenda
- Setup project next
- การใช้ component ใน Next
- App Routing ของ next (ทำ route แต่ละหน้า)
- ปรัชญาระหว่าง App Router และ Pages router
- Data fetching
- รู้จักกับ Server component และ Client Component
- Deploy ขึ้น vercel
เราจะมาทำเว็บ blog กันโดยยังคงใช้ mockapi เป็นแหล่งของ API ในการทำ
Setup project
Ref: https://nextjs.org/docs/getting-started/installation
และเลือกใช้ค่า default ทั้งหมด
- เพื่อความงดงามและให้แต่ง style ง่ายขึ้น เราจะเลือกใช้ tailwind เพิ่มเข้ามา
start project
เว็บจะโดนเปิดมาที่ port 3000 เป็นค่า default
Routing
Ref: https://nextjs.org/docs/app/building-your-application/routing/defining-routes
Routing คือการจัดการ web app ให้ออกมามี path ที่ถูกต้องตามที่เราต้องการได้
ข้อสังเกตุแรก
- ตรงส่วนด้านบนมีปรับ App Router และ Pages Router คู่กันเอาไว้
ท่าการทำ routing ใน Next มี 2 ท่าคือ
- Pages Router = ใช้ folder pages ในการ control route (เป็นค่า default เก่าตั้งแต่ Next version ก่อน 14)
- App Router = ใช้ folder app ในการ control pages (เป็นท่า default ปัจจุบัน)
Reminder ทุกท่าที่เราจะใช้ในนี้จะเป็นท่าของ App Router (เนื่องจาก Next.js support ท่านี้เป็น default ไว้แล้ว)
- หากใครยังมีความจำเป็นใช้ Pages Router อยู่ ฟัง concept แล้วลองกลับ document ดูได้
- ถ้าใครเริ่มใหม่ (ตั้งแต่ Next.js 14 เป็นต้นไป) = ใช้ท่า App Router แทน
โดยเราจะต้อง follow pattern ตามนี้คือ
- ทุกอย่างต้องสร้างภายใต้ folder
app
โดยอยากได้ path ไหนต้องระบุชื่อ folder นั้น
- ภายใน folder path นั้นๆ จะต้องสร้างไฟล์ชื่อ
page.js
เพื่อให้เป็นจุดเริ่มต้นของ path เสมอ (ถ้าไม่สร้าง = link มาหา path นั้นไม่ได้)
- หากใครใช้เป็น typescript =
.tsx
, ใครใช้เป็น javascript ปกติ =.js
เพียงเท่านี้ก็จะสามารถสร้าง path ขึ้นมาได้
Dynamic route
Ref: https://nextjs.org/docs/app/building-your-application/routing/dynamic-routes
เราสามารถทำ parameter (จากนี้ใน docs จะขอเรียก param) กับ routing ได้ผ่านวิธีการดังนี้
-
สร้างชื่อ folder เหมือนกับชื่อ param ได้โดยการตั้งชื่อ folder
[slug]
-
เราสามารถเรียกผ่านตัวแปร params ได้จาก Component ของ
page.js
ได้เลย
ex. path ชื่อ app/blog/[slug]/page.js
และ code เป็น
เมื่อเปิดผ่าน /blog/a
= ก็จะได้เป็น { slug: 'a' }
ใน params ออกมาได้
ท่าอื่นเพิ่มเติม: Catch-all Segments
- Ref: https://nextjs.org/docs/app/building-your-application/routing/dynamic-routes#optional-catch-all-segments
- กรณีที่เราจะเอาทุก path เลย (หลังจากที่มีการกำหนด path ไว้) = ท่านี้จะทำการ get ทุก path ไว้หมด
- เช่น เคส
/blog
ถ้าใช้วิธีนี้ ไม่ว่าจะเป็น/blog/1
,/blog/test/2
,/blog/m/1
ก็จะเข้าเงื่อนไขนี้ทั้งหมดได้
Route Handlers
Ref: https://nextjs.org/docs/app/building-your-application/routing/route-handlers#dynamic-functions
- ใน Next เนื่องจากเป็นการ render ที่สามารถทำได้ตั้งแต่ ฝั่ง Server มา = สามารถทำ API กับ App router ได้
โดยข้อตกลงคือ
-
สร้าง folder ที่ต้องการทำ path API
-
สร้าง file ชื่อ
route.js
เพื่อทำการเพิ่ม logic ของ api เข้าไป (จะสามารถ control ตัวแปร Request, Response ออกมาได้)
เช่น สมมุติ
- เราสร้าง file ที่ path
app/test/route.js
และใน route.js
มี code ตามนี้
เมื่อเปิดด้วย /test
ก็จะได้ JSON ออกมาได้
เท่ากับเราสามารถทำ API Server ได้ผ่านตัวของ Next นั่นเอง
เพิ่มเติม
- ชื่อ functions
GET()
คือ HTT Verb สามารถเปลี่ยนตามการใช้งานได้ เป็นGET
,POST
,PUT
,PATCH
,DELETE
,HEAD
, andOPTIONS
- สามารถเพิ่มสิ่งที่เรียกว่า cache ไปได้ผ่าน API (ควบคุมผ่านตัวแปร revalidate)
- สามารถทำ Dynamic functions โดยการเรียกใช้
cookies
และheaders
ได้ = สามารถอ่าน / เขียน header, cookie ได้ - สามารถรับ params มาด้วยไอเดียเดียวกันกับ page ได้
Middleware
https://nextjs.org/docs/app/building-your-application/routing/middleware
Middleware คือส่วนของ code ที่จะ run ก่อนที่ request จะทำงานเสร็จ
- สามารถที่จะ rewriting, redirecting, modifying ตัว request, response ก่อนที่จะไปถึงตำแหน่งจริงๆได้
กฎคือ สร้างไฟล์ชื่อ middleware.js
ไว้ที่ root project (level เดียวกันกับ app) = ได้ middleware
แล้วเรียบร้อย
ตัวอย่าง middleware.js
เคสที่เราจะมีโอกาสได้ใช้ Middleware
- Level Access Control = เฉพาะคนที่อนุญาตถึงจะเปิดได้
- User data = แนบ data user เข้ากับ request ไป จะได้ไม่ต้องเรียกใช้งานจากหลายที่
Note
- ลองสร้างหน้าของ content เพิ่มมา
- link ไปยังหน้า content นั้น (Dynamic Routing)
- ลองทำ Mock API ผ่าน Route Handler
- ลองทดสอบปิดกั้นผ่าน Middleware
Basic component / Layout / Styling
Ref: https://nextjs.org/docs/app/building-your-application/styling/css-modules https://nextjs.org/docs/pages/building-your-application/routing/pages-and-layouts
- อะไรที่ React ทำได้ยังคง support เหมือนเดิม (เช่น css module)
- เพิ่มเติมคือ CLI มีเพิ่ม tailwind มา สามารถใช้งาน tailwind คู่กันได้ (เป็น default)
- Support การทำ Layout เป็น default (สามารถระบุชื่อ file
layout.js
) ในตำแหน่งนั้นๆ
โดย layout อยู่ folder ไหนก็จะ support layout ของ folder นั้น
Note
- ทดสอบใช้ style tailwind
- เพิ่ม layout component (header / footer โดยประมาณ)
Rendering
มาทำความเข้าใจเรื่องของ Server component และ Client component ก่อน
- Client Component = React component ที่ทำการ render จากฝั่ง Client เหมือนปกติ
- React Server Component (RSC) = คือ component ที่อนุญาตให้เราเขียน UI ที่สามารถ render และ cache บางส่วนไว้บน server ได้ (นั่นคือ เป็นการ run จาก server)
Note: React Server Component คือ Default ของ Component ใน Next.js
- สำหรับการแยกส่วน Client Component และ Server Component สามารถใช้
use
ในการแยกได้ - ถ้าใช้เป็น Client component ล้วนๆ = เรียกใช้
use client
- ถ้าใช้เป็น Server component ล้วนๆ = เรียกใช้
use server
- ทุก React component ที่มีการจัดการ state = ต้องเป็น Client component
- ถ้าตัวแม่เป็น Client component อยู่แล้ว = ไม่ต้องไล่ประกาศที่ตัว child component ทุกตัวจะถือเป็น client component ทั้งหมดได้
Server component
Ref: https://nextjs.org/docs/app/building-your-application/rendering/server-components
โจทย์หลักๆของ Server component
- Data Fetching (เดี๋ยวเราจะหยิบทำในหัวข้อถัดไปอีกที)
- Security = Logic จะอยู่ในฝั่ง server แทน (สามารถเรียกใช้ API key, token จากจุดนี้ได้ มันจะไม่โผล่ไปฝั่ง client)
- Caching = สามารถเก็บ cache บน server ไว้ได้
- เพิ่มความเร็ว First Contentful Paint (FCP)
- เพิ่มการเจอของ SEO เนื่องจาก content โดน render ออกมาหน้าเว็บ = ทำให้ bot หาเจอได้ (พวก Metadata)
หลักการของ Server component
- React จะ render Server component เป็น data format ใหม่ชื่อ “React Server Component Payload (RSC Payload)”
- Next.js จะใช้ “RSC Payload” render ที่ Client Component ออกมาที่หน้าเว็บ
ที่เหลือ
- HTML ก็จะแสดงออกมาที่หน้าเว็บ
- RSC Payload จะถูกใช้สร้าง DOM Tree > และสามารถทำให้หน้าเว็บ interactive ได้ผ่านการ hydrate
เพราะฉะนั้น Server component จะเหมาะกับ โจทย์ที่ต้องมีการดึง Data โดยเฉพาะ
Client component
Ref: https://nextjs.org/docs/app/building-your-application/rendering/client-components
Client component คือ React component เลย
- จัดการ state ทุกอย่างอยู่ที่นี่
- interactive กับ javascript กับเว็บก็อยู่ที่นี่
เช่น
โจทย์หลักๆของ Client component
- สร้าง UI component ที่ reuse ได้ (ไม่สามารถใช้ setState กับฝั่ง Server component ได้จะเกิด error ทันที)
เหตุแห่งการต้องใช้ use client
ตัวอย่าง Error เมื่อไม่ประกาศ use client
ใน UI Component
การประกาศ Server / Client Component ที่ถูกต้อง
Ref: https://nextjs.org/docs/app/building-your-application/rendering/composition-patterns
Note
- เพิ่มเติมการเขียน cookie ลง API
- และฝั่ง middleware อ่านผ่าน cookie API
Data fetching
Data fetching ว่าด้วยเรื่องของการดึงข้อมูลจาก API ภายนอกมาใช้งาน
- ใน Server component เราสามารถจัดการดึงข้อมูลมาได้ผ่าน
fetch
(จะลง axios หรือดึงผ่าน proxy api อย่าง Route Handlers ที่เราทำไปก็ได้) - มี feature ที่สามารถทำ Cache ได้ (ยังไม่ลงใน Session นี้) ซึ่ง Data fetching จะมี feature อย่าง Revalidating Data ที่สามารถจัดการ cache ได้
Ref: https://nextjs.org/docs/app/building-your-application/data-fetching/patterns
ซึ่งจุดแข็งแกร่งของ Next.js ที่ Fetch data จาก Server เลยคือ
- Access backend data resource ได้เลย
- จัดการทั้งหมดผ่าน code ชุดเดียวกันได้ = ลด client-server waterfalls ได้
Note
- ลอง data fetch มาแสดงผลก่อน
การ Streaming
Ref: https://nextjs.org/docs/app/building-your-application/routing/loading-ui-and-streaming
ปัญหา classic อย่างหนึ่งของการดึงข้อมูลผ่าน Server อย่างพวก Server side render คือการที่ต้องรอข้อมูลจาก server ให้เสร็จก่อน ถึงจะไปต่อได้
อ้างอิงภาพนี้อีกรอบ
สิ่งที่มันจะเกิดขึ้นตอน load คือ
- หน้าเว็บจะไม่มี content อะไรออกมาก่อนสักแปบ
- หลังจาก server load เสร็จ = render หน้าเว็บออกมาทีเดียว
ทางแก้ของเรื่องนี้คือการใช้ Streaming
- Straming คือการ breakdown page มาเป็นส่วนเล็กๆแล้วค่อยทยอย load ไปทีละส่วน
- จะเน้นให้หน้าเว็บแสดงผลออกมาให้ได้ก่อน แล้วค่อยนำข้อมูลมาแสดงหลังจาก load เสร็จ
- จะส่งผลทำให้ FCP (display ครั้งแรก) ออกมาไวมาก
และนี่คือการ load ที่เกิดขึ้นหลังจากใช้ Streaming
ซึ่งสิ่งนี้สามารถทำได้ด้วย component <Suspense>
- สามารถทำได้โดยการ wrap Suspense component
- หรือสามารถใส่ loading ในการทำได้
Note
- ดึง data จาก mockapi มา
- เพิ่ม loading เข้าไป
Server action
Ref: https://nextjs.org/docs/app/building-your-application/data-fetching/forms-and-mutations
Server action = การเพิ่ม action server เข้าไปใน component โดยไม่จำเป็น “ต้องสร้าง API แยกออกมา”
- สามารถเรียกใช้งานได้ทั้ง Server component และ Client component (แต่ต้องประกาศการเรียกใช้ไว้)
ไอเดียการใช้งานคู่กับ page
กลับมาลอง code ตั้งแต่โจทย์ใหม่
สิ่งที่เราจะทำ Server component
- ทำดึงข้อมูล blog list ออกมา (/)
- ดึงข้อมูล blog แต่ละหน้า (/blog/:id )
- เพิิ่ม loading / layout
Client component
- หน้า Login (+ Server action) + เขียน jwt token สำหรับการ login (/login)
- เพิ่ม middleware สำหรับการเช็ค path manage ให้เฉพาะคน login เท่านั้น
- เพิ่มหน้า manage (/manage/blog) สำหรับการ list ทั้งหมด
- หน้า edit (/manage/blog/:id ) สำหรับแก้ไข blog
อื่นๆเพิ่มเติม
ในหัวข้อนี้เราอาจจะยังไม่ครอบคลุมเรื่อง
-
Auth เนื่องจากมี in detail ค่อนข้างเยอะ (เราจะกลับมาพร้อมกับหัวข้อที่ทำให้ทุกคนเห็นภาพเรื่อง auth จริงๆแน่นอน)
-
Cache โดยปกติจะมี 3 strategy ใหญ่ๆคือ
- Static Rendering
- Dynamic Rendering
- Streaming
Ref:
- https://nextjs.org/docs/app/building-your-application/rendering/server-components#static-rendering-default
- https://nextjs.org/docs/app/building-your-application/caching
Code: https://github.com/mikelopster/next-basic
- รู้จักกับ Design Pattern - Behavioral (Part 3/3)มี Video
มาเรียนรู้รูปแบบการพัฒนา Software Design Pattern ประเภทที่สาม Behavioral กัน
- มาเรียนรู้พื้นฐาน Functional Programming กันมี Video
มาเรียนรู้พื้นฐาน Functional Programming กันว่ามันคืออะไร
- รู้จักกับ Design Pattern - Creational (Part 1/3)มี Video
มาเรียนรู้รูปแบบการพัฒนา Software Design Pattern ประเภทแรก Creational กัน
- มาเรียน Canvas ผ่าน Pong game กันมี Video
มารู้จักกับ HTML Canvas ว่ามันคืออะไร ใช้ทำอะไรบ้าง และมารู้จักพื้นฐานเบื้องต้นของการทำ Animation บน Browser ว่ามีหลักการเป็นประมาณไหน