ไทย

สำรวจ unstable_cache API ของ Next.js เพื่อการควบคุมการแคชข้อมูลอย่างละเอียด ช่วยเพิ่มประสิทธิภาพและประสบการณ์ผู้ใช้ในแอปพลิเคชันไดนามิก

Next.js Unstable Cache: การควบคุมแคชอย่างละเอียดสำหรับแอปพลิเคชันแบบไดนามิก

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

ทำความเข้าใจเกี่ยวกับการแคชใน Next.js

ก่อนที่จะเจาะลึกถึง unstable_cache สิ่งสำคัญคือต้องเข้าใจเลเยอร์การแคชต่างๆ ใน Next.js Next.js ใช้กลไกการแคชหลายอย่างเพื่อปรับปรุงประสิทธิภาพ:

แม้ว่ากลไกการแคชเหล่านี้จะมีประสิทธิภาพ แต่ก็อาจไม่ได้ให้ระดับการควบคุมที่จำเป็นสำหรับแอปพลิเคชันที่ซับซ้อนและไดนามิกเสมอไป นี่คือจุดที่ unstable_cache เข้ามามีบทบาท

ขอแนะนำ `unstable_cache` API

unstable_cache API ใน Next.js ช่วยให้นักพัฒนาสามารถกำหนดกลยุทธ์การแคชแบบกำหนดเองสำหรับการดึงข้อมูลแต่ละรายการได้ โดยให้การควบคุมอย่างละเอียดในเรื่อง:

API นี้ถือว่าเป็น "unstable" (ไม่เสถียร) เนื่องจากยังอยู่ระหว่างการพัฒนาและอาจมีการเปลี่ยนแปลงใน Next.js เวอร์ชันอนาคต อย่างไรก็ตาม มันมีฟังก์ชันการทำงานที่มีค่าสำหรับสถานการณ์การแคชขั้นสูง

`unstable_cache` ทำงานอย่างไร

ฟังก์ชัน unstable_cache รับอาร์กิวเมนต์หลักสองตัว:

  1. ฟังก์ชันที่ดึงหรือคำนวณข้อมูล: ฟังก์ชันนี้ทำหน้าที่ดึงข้อมูลหรือคำนวณจริง
  2. ออบเจ็กต์ตัวเลือก (options object): ออบเจ็กต์นี้ระบุตัวเลือกการแคช เช่น TTL, แท็ก และคีย์

นี่คือตัวอย่างพื้นฐานของวิธีใช้ unstable_cache:

import { unstable_cache } from 'next/cache';

async function getData(id: string) {
  return unstable_cache(
    async () => {
      // จำลองการดึงข้อมูลจาก API
      await new Promise((resolve) => setTimeout(resolve, 1000));
      const data = { id: id, value: `Data for ID ${id}` };
      return data;
    },
    ["data", id],
    { tags: ["data", `item:${id}`] }
  )();
}

export default async function Page({ params }: { params: { id: string } }) {
  const data = await getData(params.id);
  return 
{data.value}
; }

ในตัวอย่างนี้:

คุณสมบัติหลักและตัวเลือกของ `unstable_cache`

1. Time-to-Live (TTL)

ตัวเลือก revalidate (เดิมคือ `ttl` ในเวอร์ชันทดลองก่อนหน้า) ระบุเวลาสูงสุด (เป็นวินาที) ที่ข้อมูลที่แคชไว้จะถือว่าถูกต้อง หลังจากเวลานี้ แคชจะถูก revalidate ในคำขอครั้งถัดไป

import { unstable_cache } from 'next/cache';

async function getData(id: string) {
  return unstable_cache(
    async () => {
      // จำลองการดึงข้อมูลจาก API
      await new Promise((resolve) => setTimeout(resolve, 1000));
      const data = { id: id, value: `Data for ID ${id}` };
      return data;
    },
    ["data", id],
    { tags: ["data", `item:${id}`], revalidate: 60 } // แคชเป็นเวลา 60 วินาที
  )();
}

ในตัวอย่างนี้ ข้อมูลจะถูกแคชเป็นเวลา 60 วินาที หลังจาก 60 วินาที คำขอครั้งถัดไปจะทริกเกอร์การ revalidation เพื่อดึงข้อมูลใหม่จาก API และอัปเดตแคช

ข้อควรพิจารณาทั่วไป: เมื่อตั้งค่า TTL ให้พิจารณาความถี่ในการอัปเดตข้อมูล สำหรับข้อมูลที่เปลี่ยนแปลงบ่อย TTL ที่สั้นกว่าจะเหมาะสม สำหรับข้อมูลที่ค่อนข้างคงที่ TTL ที่ยาวขึ้นสามารถปรับปรุงประสิทธิภาพได้อย่างมาก

2. Cache Tags

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

import { unstable_cache, revalidateTag } from 'next/cache';

async function getProduct(id: string) {
  return unstable_cache(
    async () => {
      // จำลองการดึงข้อมูลผลิตภัณฑ์จาก API
      await new Promise((resolve) => setTimeout(resolve, 500));
      const product = { id: id, name: `Product ${id}`, price: Math.random() * 100 };
      return product;
    },
    ["product", id],
    { tags: ["products", `product:${id}`] }
  )();
}

async function getCategoryProducts(category: string) {
  return unstable_cache(
    async () => {
      // จำลองการดึงข้อมูลผลิตภัณฑ์ตามหมวดหมู่จาก API
      await new Promise((resolve) => setTimeout(resolve, 500));
      const products = Array.from({ length: 3 }, (_, i) => ({ id: `${category}-${i}`, name: `Product ${category}-${i}`, price: Math.random() * 100 }));
      return products;
    },
    ["categoryProducts", category],
    { tags: ["products", `category:${category}`] }
  )();
}

// ทำให้แคชสำหรับผลิตภัณฑ์ทั้งหมดและผลิตภัณฑ์ที่ระบุใช้งานไม่ได้
async function updateProduct(id: string, newPrice: number) {
  // จำลองการอัปเดตผลิตภัณฑ์ในฐานข้อมูล
  await new Promise((resolve) => setTimeout(resolve, 500));

  // ทำให้แคชสำหรับผลิตภัณฑ์และหมวดหมู่ของผลิตภัณฑ์ใช้งานไม่ได้
  revalidateTag("products");
  revalidateTag(`product:${id}`);

  return { success: true };
}

ในตัวอย่างนี้:

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

3. Cache Key Generation

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

import { unstable_cache } from 'next/cache';

async function getData(userId: string, sortBy: string) {
  return unstable_cache(
    async () => {
      // จำลองการดึงข้อมูลจาก API
      await new Promise((resolve) => setTimeout(resolve, 1000));
      const data = { userId: userId, sortBy: sortBy, value: `Data for user ${userId}, sorted by ${sortBy}` };
      return data;
    },
    [userId, sortBy],
    { tags: ["user-data", `user:${userId}`] }
  )();
}

ในตัวอย่างนี้ คีย์แคชจะขึ้นอยู่กับพารามิเตอร์ userId และ sortBy สิ่งนี้ทำให้มั่นใจได้ว่าแคชจะใช้งานไม่ได้เมื่อพารามิเตอร์เหล่านี้มีการเปลี่ยนแปลง

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

4. Manual Revalidation

ฟังก์ชัน `revalidateTag` ช่วยให้คุณสามารถทำให้แคชสำหรับข้อมูลที่เชื่อมโยงกับแท็กเฉพาะใช้งานไม่ได้ด้วยตนเองได้ สิ่งนี้มีประโยชน์เมื่อคุณต้องการอัปเดตแคชเพื่อตอบสนองต่อเหตุการณ์ที่ไม่ได้ถูกทริกเกอร์โดยตรงจากคำขอของผู้ใช้ เช่น background job หรือ webhook

import { revalidateTag } from 'next/cache';

async function handleWebhook(payload: any) {
  // ประมวลผลข้อมูลจาก webhook

  // ทำให้แคชสำหรับข้อมูลที่เกี่ยวข้องใช้งานไม่ได้
  revalidateTag("products");
  revalidateTag(`product:${payload.productId}`);
}

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

กรณีการใช้งานจริงสำหรับ `unstable_cache`

1. เนื้อหาไดนามิกที่มีการอัปเดตไม่บ่อย

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

2. ข้อมูลเฉพาะผู้ใช้

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

3. ข้อมูลเรียลไทม์ที่ยอมรับข้อมูลที่อาจล้าสมัยได้

สำหรับแอปพลิเคชันที่แสดงข้อมูลเรียลไทม์ (เช่น ราคาหุ้น, ฟีดโซเชียลมีเดีย) คุณสามารถใช้ unstable_cache กับ TTL สั้นๆ เพื่อให้มีการอัปเดตที่ใกล้เคียงเรียลไทม์ สิ่งนี้สร้างความสมดุลระหว่างความต้องการข้อมูลล่าสุดกับประโยชน์ด้านประสิทธิภาพของการแคช

4. A/B Testing

ในระหว่างการทำ A/B testing สิ่งสำคัญคือต้องแคชตัวแปรการทดลองที่กำหนดให้กับผู้ใช้เพื่อให้แน่ใจว่าได้รับประสบการณ์ที่สอดคล้องกัน สามารถใช้ `unstable_cache` เพื่อแคชตัวแปรที่เลือกโดยใช้ ID ของผู้ใช้เป็นส่วนหนึ่งของคีย์แคชได้

ประโยชน์ของการใช้ `unstable_cache`

ข้อควรพิจารณาและแนวทางปฏิบัติที่ดีที่สุด

`unstable_cache` กับการแคชของ `fetch` API

Next.js ยังมีความสามารถในการแคชในตัวผ่าน fetch API โดยค่าเริ่มต้น Next.js จะแคชผลลัพธ์ของคำขอ fetch โดยอัตโนมัติ อย่างไรก็ตาม unstable_cache มีความยืดหยุ่นและการควบคุมที่มากกว่าการแคชของ fetch API

นี่คือการเปรียบเทียบของทั้งสองวิธี:

คุณสมบัติ `unstable_cache` `fetch` API
การควบคุม TTL กำหนดค่าได้โดยตรงด้วยตัวเลือก revalidate จัดการโดย Next.js โดยปริยาย แต่สามารถมีอิทธิพลได้ด้วยตัวเลือก revalidate ใน fetch options
แท็กแคช รองรับแท็กแคชสำหรับการทำให้ข้อมูลที่เกี่ยวข้องใช้งานไม่ได้ ไม่มีการรองรับในตัวสำหรับแท็กแคช
การปรับแต่งคีย์แคช อนุญาตให้ปรับแต่งคีย์แคชด้วยอาร์เรย์ของค่าที่ใช้สร้างคีย์ ตัวเลือกการปรับแต่งมีจำกัด คีย์ได้มาจาก URL ของ fetch
การ Revalidate ด้วยตนเอง รองรับการ revalidate ด้วยตนเองด้วย revalidateTag การรองรับการ revalidate ด้วยตนเองมีจำกัด
ความละเอียดของการแคช อนุญาตให้แคชการดำเนินการดึงข้อมูลแต่ละรายการ เน้นที่การแคชการตอบสนองของ HTTP เป็นหลัก

โดยทั่วไปแล้ว ให้ใช้การแคชของ fetch API สำหรับสถานการณ์การดึงข้อมูลอย่างง่ายที่พฤติกรรมการแคชเริ่มต้นเพียงพอ ใช้ unstable_cache สำหรับสถานการณ์ที่ซับซ้อนมากขึ้นซึ่งคุณต้องการการควบคุมพฤติกรรมการแคชอย่างละเอียด

อนาคตของการแคชใน Next.js

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

สรุป

unstable_cache API ของ Next.js มอบการควบคุมการแคชข้อมูลอย่างที่ไม่เคยมีมาก่อนให้กับนักพัฒนา ช่วยให้พวกเขาสามารถเพิ่มประสิทธิภาพและประสบการณ์ผู้ใช้ในแอปพลิเคชันไดนามิกได้ ด้วยความเข้าใจในคุณสมบัติและประโยชน์ของ unstable_cache คุณสามารถใช้ประโยชน์จากพลังของมันเพื่อสร้างเว็บแอปพลิเคชันที่เร็วขึ้น ปรับขนาดได้มากขึ้น และตอบสนองได้ดียิ่งขึ้น อย่าลืมพิจารณากลยุทธ์การแคชของคุณอย่างรอบคอบ เลือกค่า TTL ที่เหมาะสม ออกแบบคีย์แคชของคุณอย่างมีประสิทธิภาพ และตรวจสอบประสิทธิภาพของแคชเพื่อให้ได้ผลลัพธ์ที่ดีที่สุด โอบรับอนาคตของการแคชใน Next.js และปลดล็อกศักยภาพสูงสุดของเว็บแอปพลิเคชันของคุณ