มีอะไรใหม่บ้างใน Next.js 9

Nuttavut Thongjor

เป็นเวลากว่า 1 วันแล้วที่ Next.js ได้ปล่อยเวอร์ชัน 9 ออกมา คงถึงเวลาที่เราต้องอัพเดทกันแล้วซินะครับ ถ้างั้นไปดูสรุปสั้น ๆ จาก Next.js 9 กันดีกว่าว่ามีฟีเจอร์อะไรใหม่ ๆ บ้าง

Dynamic Routing จะไม่ใช่เรื่องยากอีกต่อไป

เราทราบกันดีว่าถ้า URL ของเราคือ /articles/intro-to-nextjs เราจำเป็นต้องสร้างไฟล์ intro-to-nextjs.js ใต้โฟลเดอร์ pages/articles การทำงานถึงจะถูกต้อง แต่หาก URL ของเราเป็น /articles/:slug โดยส่วนของ :slug สามารถเปลี่ยนแปลงได้ เราจะต้องออกแบบโฟลเดอร์ pages อย่างไรให้ Next.js เข้าใจ?

วิธีดั้งเดิมของ Next.js นั้นเราต้องทำการ ปรับแต่งเซิฟเวอร์ ด้วยตนเองซึ่งเป็นอะไรที่ค่อนข้างยุ่งยาก แพคเกจอย่าง next-routes จึงดูเป็นทางออกมากกว่า

สำหรับ Next.js 9 ที่พึ่งคลอดนั้นสนับสนุนการทำงานแบบ Dynamic Routing แต่ต้น ไม่แน่ใจว่าได้แรงบันดาลใจมาจาก Nuxt.js ของ Vue ที่ทำแบบนี้มาได้ชาติเศษแล้วรึเปล่า เพราะตัววิธีการนั้นมีความคล้ายคลึงกัน

สำหรับ Next นั้นถ้าอยากได้ URL เป็น /articles/:slug สิ่งที่เราต้องทำคือสร้างโฟลเดอร์ pages/articles/[slug].js จุดสำคัญอยู่ที่ส่วนเปลี่ยนแปลงได้ (dynamic segment) ต้องนิยามใต้เครื่องหมาย [] Next ไม่ได้จำกัดว่าคุณจะมี dynamic segment กี่จุดขอแค่ทุกจุดอยู่ใต้ [] ก็พอ เช่น /articles/[articleSlug]/comments/[commentId].js ประกอบด้วย dynamic segments สองจุดคือ :articleSlug ที่เป็นชื่อโฟลเดอร์ และ :commentId ที่เป็นไฟล์

การจะดึงส่วนของ dynamic segments มาใช้นั้น ให้ดึงจากค่าของ query ออกมาได้เลยครับ เช่น

JavaScript
1// URL: /articles/intro-to-next
2// File: pages/articles/[slug].js
3static async getInitialProps({ query }) {
4 // slug = 'intro-to-next'
5 const { slug } = query
6
7 // นำค่า slug ไปใช้งานต่อได้
8}

สร้างส่วนของ Backend API ใน Next.js ได้เลย

บางครั้งเราอยากสร้างส่วนของ API ผูกติดไว้กับการทำ Server-Side Rendering (SSR) ของ Next.js เราจึงทำการ ปรับแต่งเซิฟเวอร์ เพิ่มเติมให้ทั้งทำงานแบบ SSR ของ Next และสนับสนุนการให้บริการ API ที่เราเขียนเพิ่มเติม

Next 9 นั้นเพียงแค่เราสร้างโฟลเดอร์ api ภายใต้โฟลเดอร์ pages เราจะสามารถเรียกใช้ไฟล์ภายใต้ pages/api นั้นได้เสมือนเป็น API ของเรา เช่นสร้างไฟล์ชื่อ pages/api/articles.js เราจะได้ URL ไว้เรียกใช้คือ /api/articles

แน่นอนว่าการสร้างโฟลเดอร์และไฟล์นั้นอยู่ใต้ pages เราจึงสามารถใช้ [] เพื่อทำ dynamic routing ได้ด้วย เช่น URL ที่ระบุเป็น /api/articles/intro-to-next จะเข้าเรียกไฟล์ pages/api/articles/[slug].js เป็นต้น

สิ่งหนึ่งที่ไฟล์ใต้ api แตกต่างจากเพจทั่วไปคือต้องคืนกลับเป็น request handler function ไม่ใช่ React Component เช่น

JavaScript
1// pages/api/articles.js
2export default function handle(req, res) {
3 res.json({ articles: [] })
4}

Prefetch เมื่อ Link นั้นแสดงผลใน Viewport

Next 9 นั้นจะใช้เทคนิคของ Intersection Observer เพื่อทำการ Prefetch Link ที่ปรากฎบนหน้าจอแล้ว ความหมายคือถ้าเรามี Link อยู่ในเพจของเรา แต่ Link นั้นยังไม่โผล่เข้ามาในส่วนแสดงผล (Viewport) Next ก็จะยังไม่ทำอะไร หากแต่เมื่อสิ่งนั้นปรากฎบน Viewport แล้วไซร์ Next.js ก็จะทำการ Prefetch ข้อมูลล่วงหน้า เมื่อผู้ใช้งานตัดสินใจคลิกลิงก์นี้ในภายหลังจะทำให้รู้สึกโหลดไวขึ้น เพราะ assets ที่จำเป็นนั้นถูกโหลดมาแล้ว

เราป้องกันการทำ prefetch ได้ด้วยการระบุค่า false ลงไปใน Link ดังนี้

JavaScript
1<Link href="/terms" prefetch={false}>
2 <a>About US</a>
3</Link>

สร้าง static pages ควบคู่ไปกับการทำ server-side rendeing แบบอัตโนมัติ

static site นั้นเร็ว Next.js ก็สนับสนุนการสร้าง static site ผ่านตัวมันมานานแล้วเช่นกัน แต่นั่นทำให้คุณต้องเลือก เพราะถ้าคุณสร้างเว็บไซต์แบบ static ด้วย Next แล้ว คุณจะทำ server-side rendering ไปด้วยไม่ได้

ทำไมฉันต้องเลือกหละ? Next 9 ตัดสินใจที่จะพิจารณาส่วนของ getInitialProps จากไฟล์ต่าง ๆ ในโฟลเดอร์ pages หากไฟล์ไหนไม่ได้มีการ "หยุด" การทำงานเพื่อไปรอการร้องขอข้อมูลจาก API server นั่นแสดงว่าไฟล์นี้ทำเป็น static page ได้ Next จะดำเนินการสร้างไฟล์นี้ให้เป็น static page ในขณะที่เพจอื่นที่ยังต้องการรอข้อมูลจาก API มาทำ SSR ก็ยังคงได้รับการทำงานแบบ SSR จาก Next เช่นเดิม

ไม่ยุ่งยากกับการใช้ TypeScript อีกต่อไป

ไม่จำเป็นต้องใช้ @zeit/next-typescript ตั้งค่า .babelrc หรือ next.config.js อีกต่อไป เพราะ Next.js จะจัดการไฟล์ TypeScript ให้กับคุณอัตโนมัติ เพียงแค่เปลี่ยนนามสกุลไฟล์จาก .js เป็น .tsx แถมยังสร้างไฟล์ tsconfig.json ให้อัตโนมัติด้วยหากในโปรเจคของเราไม่มีไฟล์นี้มาก่อน

อื่น ๆ

Next.js 9 นั้นไม่ได้มีแค่สิ่งที่ผมได้แสดงในบทความนี้ หากแต่ยังมีการปรับปรุงประสิทธิภาพอื่น ๆ อีกมาก เช่น

  • มีการแสดงผลไอคอนเล็ก ๆ ด้านล่างขวาของเพจเมื่อมีการคอมไพล์โค้ดใหม่
  • ลบโค้ดของเซิฟเวอร์ที่ไม่ได้ใช้ออกไปจากโค้ดส่วนไคลเอนต์ ทำให้ bundle size ของไคลเอนต์มีขนาดเล็กลง
  • เพิ่มประสิทธืภาพการทำงานกับ AMP
  • การรายงานข้อมูลของการ build ที่ดีขึ้น

การปรับปรุงประสิทธิภาพที่น่าสนใจในอนาคต

Google ได้ร่วมมือกับ Next ด้วยการเสนอ RFC และ pull requests ที่ช่วยปรับปรุงประสิทธิภาพของ Next มีหลายตัวมากที่น่าสนใจครับ และตัวอย่างหนึ่งที่อยากนำเสนอก็คือ module/nomodule pattern

เราทราบกันดีว่ามีหลายสิ่งที่เราต้องการเขียนแต่ไม่สนับสนุนให้ทำในเบราเซอร์รุ่นเก่า แต่นั่นไม่เป็นปัญหาสำหรับเบราเซอร์ที่ใหม่กว่า เช่น เบราเซอร์เก่า ๆ ไม่สนับสนุนการทำงานกับ Async/Await แต่เบราเซอร์ยุคใหม่นั้นสนับสนุน ครั้นจะเอา polyfills ใส่ลงไปเพื่อให้เบราเซอร์เก่าทำงานได้ มันกลับเป็นหอกสองคมที่เบราเซอร์ใหม่ต้องรับภาระในการโหลดโค้ดส่วนเกิดแทน Next จึงมี RFC ที่เสนอให้ใช้หลักการของ module/nomodule pattern เพื่อสร้าง build แยกสำหรับเบราเซอร์ใหม่และเก่า ซึ่งหลักการนี้ทำมาใน Vue/Nuxt.js มาสามชาติเศษแล้ว

สรุป

Next.js 9 นั้นยังมีการปรับปรุงเรื่องอื่นอีก เพื่อน ๆ ที่สนใจสามารถเข้าไปอ่านได้จากเอกสารอ้างอิงท้ายบทความครับ

เอกสารอ้างอิง

Next.js 9. Retrieved July, 9, 2019, from https://nextjs.org/blog/next-9

สารบัญ

สารบัญ

  • Dynamic Routing จะไม่ใช่เรื่องยากอีกต่อไป
  • สร้างส่วนของ Backend API ใน Next.js ได้เลย
  • Prefetch เมื่อ Link นั้นแสดงผลใน Viewport
  • สร้าง static pages ควบคู่ไปกับการทำ server-side rendeing แบบอัตโนมัติ
  • ไม่ยุ่งยากกับการใช้ TypeScript อีกต่อไป
  • อื่น ๆ
  • การปรับปรุงประสิทธิภาพที่น่าสนใจในอนาคต
  • สรุป
  • เอกสารอ้างอิง