ทำไมเราถึงควรใช้ app router ใน next 13

foursqweez
ChomCHOB
Published in
4 min readSep 20, 2023

เกริ่นนำ

บทความนี้จะพูดถึงการใช้งาน app router ใน next 13 ซึ่งเป็น feature ที่น่าสนใจมาก เนื่องจากจำนวน code ที่ดูสั้นลงและความยืดหยุ่นที่มากขึ้น โดยจะเปรียบเทียบกับ pages router ซึ่งเป็นตัวเดิมว่ามีความแตกต่างกันอย่างไร และวิธีใช้ต่างกันยังไง ซึ่งถ้าจะให้ดีบทความนี้ผู้อ่านควรมีความรู้พื้นฐานเรื่อง React หรือ Next มาก่อนนะ

ความประทับใจแรกกับ Next js

Router ใน Next js นี่มันสะดวกดีนะ แค่ไปสร้างไฟล์ index.js ไว้ใน Folder Pages ก็จะได้ Route มาเลย ไม่ต้องไปสร้างเองแบบของ React

โดยการใช้งานก็สะดวกและง่าย มาก ๆ แบบนี้

ภาพจาก next js official document

จากภาพด้านบน ถ้าเรา Run project แล้ว เปิดไปที่ hostname/ ก็จะเจอหน้าแรก ที่เราเขียนอะไรไว้ใน index.js เลย โดยที่ไม่ต้องไปสร้าง Route แบบของ React เองว่า ถ้า path name = “/” ให้ไปเปิดที่ component ไหน

หรือว่าถ้าเราไปสร้าง folder ชื่อว่า blog ใน pages แล้วใน blog มี index.js ถ้า path nama = ‘/blog’ ก็จะทำการแเสดงสิ่งที่เราเขียนไว้ในไฟล์ index.js ที่อยู่ในโฟลเดอร์ blog ให้เองเลย สะดวกใช่ไหมละ?

แต่เนื่องจากเจ้าตัว pages router ที่ใช้นี้ยังอยู่ใน next 12 ซึ่งยังคงไม่ยืดหยุ่นมากพอและบางอย่างถ้าจะทำอาจจะมี learning curve ที่สูงหน่อย เช่นการเชื่อมต่อ api ที่มีชื่อฟังก์ชันที่ฟังดูต้องเฉพาะเจาะจงไปหน่อยอย่าง getServerside, getStaticProps และอื่น ๆ การสร้างหน้า 404 แบบเฉพาะโฟล์เดอร์ การสร้างโฟล์เดอร์เพื่อใช้ไว้เก็บไฟล์แต่ไม่อยากให้ไปสร้างเป็น Route

เนื่องจากความไม่ยืดหยุ่นเหล่านี้ทีมพัฒนาจึงต้องสร้างบางอย่างขึ้นมาเพื่อจัดการกับปัญหานี้นั่นเอง

เปิดตัว Next 13

หลังจากที่ next13 ได้เปิดตัวอย่างเป็นทางการ เมื่อวันที่ 25 ต.ค. 2565 ในงาน Next conf ซึ่งในตอนนั้นก็มีหลาย feature ที่น่าสนใจ ซึ่งหนึ่งในนั้นก็คือ App Directory (beta) ซึ่งตอนนั้นจะยังเป็นแค่ version beta อยู่ ดังที่แสดงตามภาพนี้

https://nextjs.org/blog/next-13
ภาพจาก https://nextjs.org/blog/next-13

แต่หลังจากผ่านไปได้ไม่ถึงปีก็ได้มีการประกาศอย่างเป็นทางการในวันที่ 4 พ.ค. 2566 ใน version Next.js 13.4 ว่า App Router (เปลี่ยนชื่อ) นั้น Stable แล้ว ตามภาพนี้

ภาพจาก https://nextjs.org/blog/next-13-4

จะเห็นจากบรรทัดสุดท้ายที่บอกว่า ตอนนี้เราสามารถเอาไปใช้ใน production ได้แล้วนะ

แล้วมันต่างกันจาก Next 12 หรือ Next 13 ที่ไม่ได้ใช้ App router ยังไงล่ะ

ความแตกต่างระหว่าง App router กับ Pages router

ถ้าคนที่เคยเขียน Next js มาก่อนจะทราบดีว่า Next นั้นสะดวกในการทำเว็บมาก ๆ ซึ่งหนึ่งในความสะดวกที่เด่นมาก ๆ ก็คือการที่เราไม่จำเป็นจะต้องสร้าง Route เอง

ซึ่งก่อนที่ App router จะเปิดตัว เราก็จะใช้ Pages router กัน

มาดูตัวอย่างกัน

Pages router

Project Structure

การที่ next js จะสามารถสร้าง route ให้เราได้นั้นก็ตามชื่อเลย Pages router นั่นหมายความว่า เราต้องสร้าง file ที่เราต้องการให้ มี route ไว้ในโฟล์เดอร์ pages ที่ next สร้างมาให้เป็นค่า default ตั้งแต่แรกอยู่แล้ว

จากภาพ เราจะสร้างโฟลเดอร์ที่มีชื่อว่า merge, mint และอื่น ๆ โดยที่ด้านใน โฟล์เดอร์จะมีไฟล์ชื่อว่า index.tsx และในนั้นเราสามารถสร้าง component ได้เลย ซึ่ง next js จะทำการสร้าง route ให้เอง โดยอัตโนมัติ โดยมีชื่อ route ตามชื่อโฟลเดอร์ที่เราสร้างนั่นเอง เช่น

ถ้าเราเปิดไปที่หน้า /mint บนเว็บบราวเซอร์ เราก็จะเจอ content ที่เราสร้างไว้ในไฟล์ pages/mint/index.tsx นั่นเอง

404 page

จากภาพด้านบนจะเห็นไฟล์ชื่อ 404.tsx ซึ่งก็คือไฟล์ที่ไว้ใช้ในการ custom handle error เมื่อ path ผิดนั่นเอง

fetch data

ตอนนั้นก็ว่าสะดวกดีนะ แต่ด้วยความสามารถที่เค้าเคลมมาในเรื่องของ ssr, ssg, หรืออื่น ๆ การที่เราจะใช้ feature พวกนี้ได้นั้นจำเป็นต้อง สร้างฟังก์ชันที่มีชื่อตามที่ next js กำหนดมาดังนี้

folder : pages/index.js

getServerSideProps() เป็นการบอกว่าเราจะใช้ การ fetch แบบ server side นะ ซึ่งวิธีสังเกตง่าย ๆ คือ ลองใช้ console.log(data) ดูก็จะเห็นว่า log ของเราจะไม่แสดงที่ browser(client) แต่จะแเสดงที่ comand line แทน

และยังมีการ fetch ในแบบต่าง ๆ อีกเช่น

getStaticProps() + getStaticPath() ไว้ใช้กับ static web ซึ่งมันจะสร้าง HTML page ไว้ตั้งแต่ตอน build อย่างถ้าเราจะมีหน้า career, about us, home มันก็จะสร้างไว้ก่อนเลยตั้งแต่ตอน build

ซึ่งก็มีท่าต่าง ๆ ให้เลือกใช้อีกแต่ขอไม่พูดถึง แต่สามารถอ่านเพิ่มเติมได้ใน doc ของ nextjs ซึ่งทำไว้ดีมาก

ที่กล่าวมาก็เพื่อที่จะบอกว่าเหมือนจะสะดวกแต่ก็ยังต้องจำนะ ซึ่งจะเขียนทีไรก็ยังต้องเปิด doc

App router

Project Structure

พอเป็น app router เราคงเดากันได้ว่ามันจะต่างกันยังไง ก็คือเราต้อง สร้างไฟล์ที่อยากให้ next js สร้าง route ให้เราไว้ในโฟลเดอร์ app แทน pages นั่นเอง แต่ในโฟล์เดอร์นี้ เราต้องเปลี่ยนการตั้งชื่อไฟล์จาก index.tsx เป็น page.tsx แทนนะ

จากภาพ next js จะทำการสร้าง route ต่าง ๆ ให้เราตามชื่อโฟลเดอร์ที่เราสร้างไว้ใน app ถ้าเราเปิดเว็บบราวเซอร์ไปที่ /cart เราก็จะเห็น content ต่าง ๆ ที่เราสร้างเก็บไว้ในไฟล์ app/cart/page.tsx

fetch data

เราจะสามารถเรียก fetch ใน โฟลเดอร์ app/page.js ได้เลย เพราะว่าใน app router component หรือ ไฟล์ ที่เราสร้าง จะเป็น server-component by default ส่วนเรื่องแบบไหนคือ static หรือ serverside ขอไม่พูดถึงในนี้ และถ้าเราจะใช้พวก client state ต่าง ๆ เราจะต้อง ประกาศ ‘use client’ ไว้ที่ด้านบนสุดของไฟล์นั้น ๆ

not-found page

ตัวนี้จะทำงานคล้าย ๆ ตัว 404.tsx ใน pages router ต่างกันตรงที่ชื่อไฟล์ต้องเป็นคำว่า not-found เท่านั้น และความต่างอีกอย่างที่น่าสนใจมาก ๆ ก็คือ ใน app router เราสามารถใช้อ feature ที่ชื่อว่า route group ได้

ซึ่งการที่เรามี route group นั้นทำให้เราสามารถมีหน้า 404 มากกว่าหนึ่งหน้าได้ตามโฟล์เดอร์นั้น ๆ

และเรายังสามารถเรีบกใช้ฟังก์ชัน notFount() เพื่อบังคับให้ไปที่หน้า 404 ได้โดยตรงอีกด้วยแบบนี้

Route Groups

โดยปกติแล้วถ้าเราสร้าง folder ไว้ใน app นั่นจะหมายความว่าเราต้องการให้ next js สร้าง route นั้นขึ้นมา แต่ถ้าเกิดว่าเราต้องการแค่ folder ไว้เก็บของในนั้นโดยที่ไม่อยากให้มันรกล่ะจะทำยังไง

จากพาจะเห็นว่ามี สองโฟลเดอร์ที่ชื่อว่า (marketing) และ (shop) ที่เห็นแล้วต้องเอะ? อะไรหว่า

ใช่แล้วนี้ก็คือ route group นั่นเอง โดยวิธีใช้ก็ง่าย ๆ แค่เพิ่มวงเล็บแบบนี้เข้าไป (folderName)

ซึ่งสิ่งที่เกิดขึ้นก็คือ next js จะไม่ทำการสร้าง route ให้เราเมื่อเราไปที่ /about หรือ /account ก็จะทำงานได้ปกติ ซึ่ง (marketing) หรือ (shop) มีหน้าที่แค่แยกให้ดดูเป็นระเบียบมากขึ้นเท่านั้นเอง

Nesting Layouts

ปกติเราจะใช้ layout ในการครอบตัวแอปของเราทั้งแอปแล้วเอาอะไรที่เราต้องการให้แสดงทุกหน้าโดยที่ไม่ต้องเอาไปใส่ไว้ในทุกไฟล์เช่น Navbar หรือ Footer

แล้วถ้าบางหน้าเราไม่ต้องการ Navbar หรือต้องการแบบอื่นล่ะจะทำยังไง สามารถทำได้หลายวิธี โดยวิธีที่คิดออกง่ายที่สุดก็คือ การ ดูว่าตอนนี้เราอยู่ที่ route ไหน ต้องการให้ render Navbar ตัวไหน

อันนี้แค่เขียนให้ดูเงื่อนไข ส่วนการจะได้มาของตัวแปร isOnPage1 ก็คือต้องเช็คจาก next router อีกที

ซึ่ง next 13 ก็ได้คิดวิธีที่ง่ายกว่าขึ้นมาแบบนี้

ซึ่งจากภาพจะเห็นว่ามีไฟล์ชื่อ layout.js สองไฟล์ แต่อยู่คนละโฟล์เดอร์ซึ่งสิ่งที่จะเกิดขึ้นก็คือเราไม่จำเป็น ต้องไปสร้างเงื่อนไขในการแสดง Navbar1, Navbar2 แล้ว แค่เอา component ตัวนั้น ๆ ไปไว้ในไฟล์ layout.js ตามโฟล์เดอร์ที่ต้องการจะให้แสดงก็พอ

ปัญหาที่ใช้มาแล้วพบ

  • next/link, next/router ไม่ทำงาน เมื่ออยู่ในหน้า not-found ต้องหาวิธี ซึ่งมีคนทำไว้ให้แล้ว!

สรุป

app router ช่วยให้เราทำงานสะดวกขึ้น มีระเบียบขึ้น เขียนโค้ดสั้นลง และเรียนรู้ได้ไม่ยากโดยใน app router และ next 13 ยังมี feature อื่น ๆ ที่น่าสนใจอีกเยอะ และ document ก็ทำออกมาได้ดี มาก ๆ ไปลองดูกันได้

เนื่องจากผมยังเป็นแค่ junior dev ตาดำ ๆ และบทความนี้เป็นบทความแรกของผม ถ้าผิดพลาดตรงไหน หรือเขียนไม่ค่อยเข้าใจ ก็ขออภัยด้วยครับ แสดงความคิดเห็น หรือแนะนำได้เต็มที่ แต่อย่าแรงมาก ขอบคุณครับ!

--

--