คู่มือฉบับสมบูรณ์สำหรับการฟื้นฟูแบบคงที่ที่เพิ่มขึ้น (ISR) ด้วย Next.js

เผยแพร่แล้ว: 2022-03-10
สรุปอย่างย่อ ↬ Incremental Static Regeneration (ISR) เป็นวิวัฒนาการใหม่ของ Jamstack ช่วยให้คุณสามารถอัปเดตเนื้อหาแบบคงที่ได้ทันทีโดยไม่จำเป็นต้องสร้างไซต์ของคุณใหม่ทั้งหมด วิธีไฮบริดของ Next.js ช่วยให้คุณใช้ ISR สำหรับอีคอมเมิร์ซ เพจทางการตลาด บล็อกโพสต์ สื่อที่มีโฆษณาสนับสนุน และอื่นๆ

ปีที่แล้ว Next.js 9.3 ได้ออกการสนับสนุนสำหรับ Static Site Generation (SSG) ทำให้เป็นเฟรมเวิร์กไฮบริดแรก ฉันเป็นผู้ใช้ Next.js ที่มีความสุขมาสองสามปีแล้ว แต่รุ่นนี้ทำให้ Next.js เป็นโซลูชันเริ่มต้นใหม่ของฉัน หลังจากทำงานกับ Next.js อย่างกว้างขวาง ฉันเข้าร่วม Vercel เพื่อช่วยเหลือบริษัทต่างๆ เช่น Tripadvisor และ Washington Post เมื่อพวกเขาปรับใช้และปรับขนาด Next.js

ในบทความนี้ ฉันต้องการสำรวจวิวัฒนาการใหม่ของ Jamstack: Incremental Static Regeneration (ISR) ด้านล่างนี้ คุณจะพบคำแนะนำเกี่ยวกับ ISR — รวมถึงกรณีการใช้งาน การสาธิต และการแลกเปลี่ยน

ปัญหาเกี่ยวกับการสร้างไซต์แบบคงที่

แนวคิดเบื้องหลัง Jamstack นั้นน่าสนใจ: หน้าสแตติกที่แสดงผลล่วงหน้าซึ่งสามารถผลักไปที่ CDN และพร้อมใช้งานทั่วโลกในไม่กี่วินาที เนื้อหาแบบคงที่นั้นรวดเร็ว ยืดหยุ่นต่อการหยุดทำงาน และจัดทำดัชนีโดยโปรแกรมรวบรวมข้อมูลทันที แต่มีปัญหาบางอย่าง

หากคุณใช้สถาปัตยกรรม Jamstack ขณะสร้างไซต์สแตติกขนาดใหญ่ คุณอาจต้องรอเป็นเวลาหลายชั่วโมงในการสร้างไซต์ของคุณ หากคุณเพิ่มจำนวนหน้าเป็นสองเท่า เวลาในการสร้างก็เพิ่มขึ้นเป็นสองเท่าด้วย ลองพิจารณา Target.com เป็นไปได้ไหมที่จะสร้างผลิตภัณฑ์นับล้านแบบคงที่ในการปรับใช้ทุกครั้ง?

สร้างกราฟเวลา
ปัญหากับการสร้างไซต์แบบคงที่: เนื่องจากเวลาในการสร้างเป็นเส้นตรงตามจำนวนหน้า คุณอาจต้องรอเป็นเวลาหลายชั่วโมงในการสร้างไซต์ของคุณ (ตัวอย่างขนาดใหญ่)

แม้ว่าทุกหน้าจะถูกสร้างขึ้นแบบคงที่ใน 1ms ที่ไม่สมจริง แต่ก็ยังต้องใช้เวลา หลายชั่วโมงในการสร้างเว็บไซต์ใหม่ทั้งหมด สำหรับเว็บแอปพลิเคชันขนาดใหญ่ การเลือกการสร้างไซต์สแตติกแบบ สมบูรณ์ ไม่ใช่การเริ่มต้น ทีมขนาดใหญ่ต้องการโซลูชันไฮบริดที่ยืดหยุ่นและเป็นส่วนตัวมากขึ้น

ระบบจัดการเนื้อหา (CMS)

สำหรับหลายๆ ทีม เนื้อหาของเว็บไซต์จะถูกแยกออกจากโค้ด การใช้ Headless CMS ช่วยให้ผู้แก้ไขเนื้อหาสามารถเผยแพร่การเปลี่ยนแปลงได้โดยไม่ต้องเกี่ยวข้องกับนักพัฒนา อย่างไรก็ตาม สำหรับไซต์สแตติกดั้งเดิม กระบวนการนี้อาจช้า

พิจารณาร้านค้าอีคอมเมิร์ซที่มีสินค้า 100,000 รายการ ราคาสินค้าเปลี่ยนแปลงบ่อย เมื่อผู้แก้ไขเนื้อหาเปลี่ยนราคาของหูฟังจาก 100 ดอลลาร์เป็น 75 ดอลลาร์ซึ่งเป็นส่วนหนึ่งของการส่งเสริมการขาย CMS ของพวกเขาจะใช้เว็บฮุคเพื่อสร้างเว็บไซต์ใหม่ทั้งหมด เป็นไปไม่ได้ที่จะรอเป็นเวลาหลายชั่วโมงเพื่อให้ราคาใหม่แสดงขึ้น

การสร้างแบบยาวด้วยการคำนวณที่ไม่จำเป็นอาจมีค่าใช้จ่ายเพิ่มเติมเช่นกัน ตามหลักการแล้ว แอปพลิเคชันของคุณฉลาดพอที่จะเข้าใจว่าผลิตภัณฑ์ใดบ้างที่เปลี่ยนแปลงและอัปเดตหน้าเหล่านั้น ทีละน้อย โดยไม่ต้องสร้างใหม่ ทั้งหมด

เพิ่มเติมหลังกระโดด! อ่านต่อด้านล่าง↓

การฟื้นฟูแบบคงที่ที่เพิ่มขึ้น (ISR)

Next.js ให้คุณสร้างหรืออัปเดตหน้าคงที่ หลังจากที่ คุณสร้างไซต์ของคุณแล้ว Incremental Static Regeneration (ISR) ช่วยให้นักพัฒนาและผู้แก้ไขเนื้อหาสามารถใช้การสร้างแบบคงที่บนพื้นฐานต่อหน้า โดยไม่ต้องสร้างเว็บไซต์ใหม่ทั้งหมด ด้วย ISR คุณสามารถรักษาประโยชน์ของสแตติกไว้ได้ในขณะที่ปรับขนาดเป็นล้านหน้า

สามารถสร้างเพจแบบสแตติกได้ที่รันไทม์ (ตามต้องการ) แทนที่จะสร้างในเวลาบิลด์ด้วย ISR เมื่อใช้การวิเคราะห์ การทดสอบ A/B หรือเมตริกอื่นๆ คุณจะมีความยืดหยุ่นในการสร้างการแลกเปลี่ยนของคุณเองกับเวลาในการสร้าง

พิจารณาร้านค้าอีคอมเมิร์ซเมื่อก่อนด้วยผลิตภัณฑ์ 100,000 รายการ ที่เวลาจริง 50 มิลลิวินาทีในการสร้างหน้าผลิตภัณฑ์แต่ละหน้าแบบคงที่ จะใช้เวลา เกือบ 2 ชั่วโมงหากไม่มี ISR ด้วย ISR เราสามารถเลือกได้จาก:

  • สร้างได้เร็วขึ้น
    สร้างผลิตภัณฑ์ยอดนิยม 1,000 รายการในเวลาสร้าง คำขอที่ทำกับผลิตภัณฑ์อื่นจะพลาดแคชและสร้างแบบคงที่ตามความต้องการ: บิลด์ 1 นาที
  • อัตราแคชที่สูงขึ้น
    สร้างผลิตภัณฑ์ 10,000 รายการในเวลาบิลด์ เพื่อให้แน่ใจว่ามีการแคชผลิตภัณฑ์เพิ่มเติมก่อนคำขอของผู้ใช้: บิลด์ 8 นาที
ภาพประกอบแสดง Jamstack ทางด้านซ้ายและ Incremental Static Regeneration ทางด้านขวา
ข้อได้เปรียบของ ISR: คุณมีความยืดหยุ่นในการเลือกว่าจะให้เพจใดสร้างตามบิลด์หรือออนดีมานด์ เลือกจาก (A) บิลด์ที่เร็วกว่าหรือ (B) แคชเพิ่มเติม (ตัวอย่างขนาดใหญ่)

มาดูตัวอย่างของ ISR สำหรับหน้าผลิตภัณฑ์อีคอมเมิร์ซกัน

เริ่มต้น

กำลังดึงข้อมูล

หากคุณไม่เคยใช้ Next.js มาก่อน ขอแนะนำให้อ่าน Getting Started With Next.js เพื่อทำความเข้าใจพื้นฐาน ISR ใช้ Next.js API เดียวกันเพื่อสร้างหน้าสแตติก: getStaticProps โดยการระบุการตรวจสอบความถูกต้องอีกครั้ง revalidate: 60 เราแจ้งให้ Next.js ใช้ ISR สำหรับหน้านี้

ไดอะแกรมของโฟลว์การร้องขอสำหรับ Incremental Static Regeneration
ไดอะแกรมของโฟลว์การร้องขอสำหรับ Incremental Static Regeneration (ตัวอย่างขนาดใหญ่)
  1. Next.js สามารถกำหนดเวลาตรวจสอบซ้ำต่อหน้าได้ ให้ตั้งค่าไว้ที่ 60 วินาที
  2. คำขอเริ่มต้นที่หน้าผลิตภัณฑ์จะแสดงหน้าแคชพร้อมราคาเดิม
  3. ข้อมูลสำหรับผลิตภัณฑ์ได้รับการอัพเดตใน CMS
  4. คำขอใด ๆ ที่ไปยังหน้าหลังจากคำขอเริ่มต้นและก่อน 60 วินาทีจะถูกแคชและทันที
  5. หลังจากหน้าต่าง 60 วินาที คำขอถัดไปจะยังคงแสดงหน้าแคช (เก่า) Next.js เรียกการสร้างหน้าเว็บ ในพื้นหลัง ขึ้นใหม่
  6. เมื่อสร้างหน้าสำเร็จแล้ว Next.js จะทำให้แคชใช้ไม่ได้และแสดงหน้าผลิตภัณฑ์ที่อัปเดต หากการสร้างพื้นหลังล้มเหลว หน้าเก่าจะไม่มีการเปลี่ยนแปลง
 // pages/products/[id].js export async function getStaticProps({ params }) { return { props: { product: await getProductFromDatabase(params.id) }, revalidate: 60 } }

การสร้างเส้นทาง

Next.js กำหนดว่าผลิตภัณฑ์ใดที่จะสร้างในเวลาบิลด์และแบบออนดีมานด์ มาสร้างผลิตภัณฑ์ 1,000 รายการที่ได้รับความนิยมสูงสุดในเวลาบิวด์โดยระบุรายการรหัสผลิตภัณฑ์ 1,000 อันดับแรกของ getStaticPaths

เราจำเป็นต้องกำหนดค่าว่า Next.js จะ "ใช้ทางเลือก" อย่างไรเมื่อร้องขอผลิตภัณฑ์อื่นๆ หลังจากการสร้างเริ่มต้น มีสองตัวเลือกให้เลือก: blocking และ true

  • fallback: blocking (แนะนำ)
    เมื่อมีการส่งคำขอไปยังหน้าที่ยังไม่ได้สร้าง Next.js จะแสดงหน้าของเซิร์ฟเวอร์ในคำขอแรก คำขอในอนาคตจะให้บริการไฟล์แบบคงที่จากแคช
  • fallback: true
    เมื่อมีการส่งคำขอไปยังหน้าที่ยังไม่ได้สร้าง Next.js จะแสดงหน้าคงที่พร้อมสถานะการโหลดในคำขอแรกทันที เมื่อข้อมูลโหลดเสร็จแล้ว หน้าจะแสดงข้อมูลใหม่อีกครั้งและแคชไว้ คำขอในอนาคตจะให้บริการไฟล์แบบคงที่จากแคช
 // pages/products/[id].js export async function getStaticPaths() { const products = await getTop1000Products() const paths = products.map((product) => ({ params: { id: product.id } })) return { paths, fallback: 'blocking' } }

การประนีประนอม

Next.js ให้ความสำคัญกับผู้ใช้ปลายทางเป็นอันดับแรก “ทางออกที่ดีที่สุด” นั้นสัมพันธ์กันและแตกต่างกันไปตามอุตสาหกรรม กลุ่มเป้าหมาย และลักษณะของแอปพลิเคชัน โดยการอนุญาตให้นักพัฒนาเปลี่ยนระหว่างโซลูชันโดยไม่ต้องออกจากกรอบงาน Next.js ช่วยให้คุณเลือกเครื่องมือที่เหมาะสมสำหรับโครงการ

การแสดงผลฝั่งเซิร์ฟเวอร์

ISR ไม่ใช่วิธีแก้ปัญหาที่ถูกต้องเสมอไป ตัวอย่างเช่น ฟีดข่าวของ Facebook ไม่สามารถแสดงเนื้อหาที่ล้าสมัยได้ ในกรณีนี้ คุณต้องการใช้ SSR และอาจเป็นส่วนหัว cache-control ของคุณเองด้วยคีย์ตัวแทนเพื่อทำให้เนื้อหาใช้ไม่ได้ เนื่องจาก Next.js เป็นเฟรมเวิร์กแบบไฮบริด คุณจึงสามารถแลกเปลี่ยนตัวเองและอยู่ภายในเฟรมเวิร์กได้

 // You can cache SSR pages at the edge using Next.js // inside both getServerSideProps and API Routes res.setHeader('Cache-Control', 's-maxage=60, stale-while-revalidate');

SSR และ edge caching นั้นคล้ายกับ ISR (โดยเฉพาะอย่างยิ่งถ้าใช้ stale-while-revalidate caching headers) โดยมีความแตกต่างหลัก ๆ คือคำขอ แรก ด้วย ISR คำขอแรกสามารถรับประกันว่าจะคงที่หากแสดงผลล่วงหน้า แม้ว่าฐานข้อมูลของคุณจะหยุดทำงาน หรือมีปัญหาในการสื่อสารกับ API ผู้ใช้ของคุณจะยังเห็นหน้าสแตติกที่แสดงอย่างถูกต้อง อย่างไรก็ตาม SSR จะอนุญาตให้คุณปรับแต่งเพจของคุณตามคำขอที่เข้ามา

หมายเหตุ : การใช้ SSR โดยไม่แคชอาจทำให้ประสิทธิภาพต่ำ ทุกมิลลิวินาทีมีความสำคัญเมื่อบล็อกผู้ใช้ไม่ให้เห็นเว็บไซต์ของคุณ และอาจส่งผลกระทบอย่างมากต่อ TTFB ของคุณ (Time to First Byte)

การสร้างไซต์แบบคงที่

ISR ไม่สมเหตุสมผลสำหรับเว็บไซต์ขนาดเล็กเสมอไป หากระยะเวลาการตรวจสอบซ้ำของคุณมากกว่าเวลาที่ใช้ในการสร้างไซต์ใหม่ทั้งหมด คุณอาจใช้การสร้างไซต์สแตติกแบบเดิมได้เช่นกัน

การแสดงผลฝั่งไคลเอ็นต์

หากคุณใช้ React โดยไม่มี Next.js แสดงว่าคุณกำลังใช้การเรนเดอร์ฝั่งไคลเอ็นต์ แอปพลิเคชันของคุณแสดงสถานะการโหลด ตามด้วยการร้องขอข้อมูลภายใน JavaScript ที่ฝั่งไคลเอ็นต์ (เช่น useEffect ) แม้ว่าสิ่งนี้จะเพิ่มตัวเลือกของคุณสำหรับการโฮสต์ (เนื่องจากไม่จำเป็นต้องใช้เซิร์ฟเวอร์) แต่ก็มีข้อแลกเปลี่ยน

การขาดเนื้อหาที่แสดงผลล่วงหน้าจาก HTML เริ่มต้นทำให้ Search Engine Optimization (SEO) ทำงานช้าลงและมีไดนามิกน้อยลง นอกจากนี้ยังไม่สามารถใช้ CSR โดยปิดการใช้งาน JavaScript

ISR ทางเลือกสำรอง

หากสามารถดึงข้อมูลได้อย่างรวดเร็ว ให้ลองใช้ fallback: blocking จากนั้น คุณไม่จำเป็นต้องพิจารณาสถานะการโหลด และหน้าเว็บของคุณจะแสดงผลลัพธ์เดียวกันเสมอ (ไม่ว่าจะแคชไว้หรือไม่ก็ตาม) หากการดึงข้อมูลของคุณช้า fallback: true จะทำให้คุณสามารถแสดงสถานะการโหลดแก่ผู้ใช้ได้ทันที

ISR: ไม่ใช่แค่แคช!

แม้ว่าฉันจะอธิบาย ISR ผ่านบริบทของแคชแล้ว แต่ก็ออกแบบมาเพื่อ คงหน้าที่สร้างขึ้น ระหว่างการปรับใช้ ซึ่งหมายความว่าคุณสามารถย้อนกลับได้ทันทีและไม่สูญเสียหน้าเว็บที่สร้างไว้ก่อนหน้านี้

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

  • ต่อไปนี้คือตัวอย่างการคืนค่ารหัสด้วย ISR:
  • คุณกดรหัสและรับ ID การปรับใช้ 123
  • หน้าของคุณมีการพิมพ์ผิด “นิตยสาร Smshng”
  • คุณปรับปรุงหน้าใน CMS ไม่จำเป็นต้องปรับใช้ซ้ำ
  • เมื่อหน้าของคุณแสดง “Smashing Magazine” หน้านั้นจะยังคงอยู่ในที่จัดเก็บ
  • คุณกดรหัสที่ไม่ถูกต้องและปรับใช้ ID 345
  • คุณย้อนกลับไปยังการปรับใช้ ID 123
  • คุณยังคงเห็น “นิตยสารยอดเยี่ยม”

การเปลี่ยนกลับและคงเพจคงที่อยู่นอกขอบเขตของ Next.js และขึ้นอยู่กับผู้ให้บริการโฮสต์ของคุณ โปรดทราบว่า ISR แตกต่างจากการแสดงผลเซิร์ฟเวอร์ด้วยส่วนหัว Cache-Control เนื่องจากแคชจะหมดอายุตามการออกแบบ ไม่มีการแชร์ข้ามภูมิภาคและจะถูกล้างเมื่อเปลี่ยนกลับ

ตัวอย่างของ Incremental Static Regeneration

Incremental Static Regeneration ทำงานได้ดีกับอีคอมเมิร์ซ เพจทางการตลาด บล็อกโพสต์ สื่อที่มีโฆษณาสนับสนุน และอื่นๆ

  • สาธิตอีคอมเมิร์ซ
    Next.js Commerce เป็นชุดเริ่มต้นแบบ all-in-one สำหรับไซต์อีคอมเมิร์ซที่มีประสิทธิภาพสูง
  • การสาธิตปฏิกิริยา GitHub
    ตอบสนองต่อปัญหา GitHub เดิมและดู ISR อัปเดตหน้า Landing Page ที่สร้างขึ้นแบบคงที่
  • Static Tweets สาธิต
    โปรเจ็กต์นี้ใช้งานได้ใน 30 วินาที แต่สามารถสร้างทวีตแบบคงที่ได้ 500 ล้านรายการตามความต้องการโดยใช้ ISR

เรียนรู้ Next.js วันนี้

นักพัฒนาและทีมงานขนาดใหญ่กำลังเลือก Next.js สำหรับแนวทางแบบไฮบริดและความสามารถในการสร้างเพจตามความต้องการแบบค่อยเป็นค่อยไป ด้วย ISR คุณจะได้รับประโยชน์จากการทำงานแบบคงที่พร้อมความยืดหยุ่นในการแสดงผลเซิร์ฟเวอร์ ISR ทำงานนอกกรอบโดยใช้ next start

Next.js ได้รับการออกแบบสำหรับการนำไปใช้อย่างค่อยเป็นค่อยไป ด้วย Next.js คุณสามารถใช้โค้ดที่มีอยู่ต่อไปและเพิ่ม React ได้มาก (หรือน้อย) ตามที่คุณต้องการ เมื่อเริ่มต้นทีละน้อยและเพิ่มทีละหน้า คุณสามารถป้องกันการทำงานของคุณลักษณะที่ทำให้ตกรางได้โดยหลีกเลี่ยงการเขียนใหม่ทั้งหมด เรียนรู้เพิ่มเติมเกี่ยวกับ Next.js — และขอให้ทุกคนสนุกกับการเขียนโค้ด!

อ่านเพิ่มเติม

  • เริ่มต้นใช้งาน Next.js
  • การเปรียบเทียบวิธีการจัดแต่งทรงผมใน Next.js
  • วิธีสร้างเซิร์ฟเวอร์ GraphQL โดยใช้เส้นทาง API ของ Next.js