ในบทช่วยสอนนี้ เราจะเข้าใจ React Server Components และด้วยความรู้ดังกล่าว เราจะสร้างตัวนับมุมมองแบบง่ายสำหรับแอปของคุณร่วมกัน อย่าลังเลที่จะข้ามไปที่การตั้งค่าโครงการหากคุณต้องการดำเนินการใช้งานต่อ
ทำความเข้าใจส่วนประกอบเซิร์ฟเวอร์ React
เพื่อให้เข้าใจถึงวิธีการทำงานของ React Server Components เราจะมาดูการเรนเดอร์ฝั่งไคลเอ็นต์ (CSR) และการเรนเดอร์ฝั่งเซิร์ฟเวอร์ (SSR) กันแบบคร่าวๆ
การแสดงผลฝั่งไคลเอ็นต์ (CSR)
ใน CSR งานการเรนเดอร์ส่วนใหญ่เกิดขึ้นในเบราว์เซอร์บนฝั่งไคลเอ็นต์:
- ผู้ใช้ร้องขอเว็บไซต์
- เซิร์ฟเวอร์ส่งไฟล์ HTML และลิงก์ไปยังไฟล์ CSS และ JS
- ลูกค้าดาวน์โหลดทรัพยากร JS
- ไคลเอนต์แสดงผลเพจโดยไม่มีเนื้อหา
- ไคลเอนต์ดึงข้อมูลจาก API ในเซิร์ฟเวอร์
- ลูกค้าเรนเดอร์เพจด้วยเนื้อหาอีกครั้ง

การเรนเดอร์ฝั่งเซิร์ฟเวอร์ (SSR)
ใน SSR เซิร์ฟเวอร์จะสร้างเนื้อหา HTML เต็มรูปแบบสำหรับแต่ละคำขอและส่งไปยังไคลเอนต์:
- ผู้ใช้ร้องขอเว็บไซต์
- เซิร์ฟเวอร์เรนเดอร์ไฟล์ HTML จริง แต่ยังไม่ได้โต้ตอบ
- ลูกค้าดาวน์โหลดทรัพยากร JS
- ในไคลเอนต์ ใช้
03ฟังก์ชัน ตัวฟังเหตุการณ์ สถานะและการโต้ตอบอื่นๆ ของส่วนประกอบ React จะแนบไปกับองค์ประกอบ DOM ที่มีอยู่ซึ่งสร้างโดยเซิร์ฟเวอร์ ซึ่งเรียกว่า ไฮเดรชั่น . - ไคลเอนต์ดึงข้อมูลจาก API ในเซิร์ฟเวอร์
- ลูกค้าเรนเดอร์เพจด้วยเนื้อหาอีกครั้ง

ข้อดีของ SSR ป>
- SEO ที่ดีขึ้น :เนื่องจากโปรแกรมรวบรวมข้อมูลของเครื่องมือค้นหาสามารถอ่าน HTML ที่เรนเดอร์ได้อย่างสมบูรณ์ SSR จึงเป็นมิตรกับ SEO มากกว่า
- การโหลดครั้งแรกเร็วขึ้น :เนื่องจากเนื้อหา HTML ที่สมบูรณ์ถูกเรนเดอร์และส่งจากเซิร์ฟเวอร์ ผู้ใช้จึงเห็นเนื้อหาของหน้าได้อย่างรวดเร็ว
ข้อเสียของ SSR ป>
- การนำทางช้าลง :คำขอเพจใหม่แต่ละรายการจำเป็นต้องมีการสื่อสารแบบไปกลับเพื่อโหลด HTML ใหม่ทั้งหมดจากเซิร์ฟเวอร์
- โหลดเซิร์ฟเวอร์เพิ่มขึ้น :เนื่องจากเซิร์ฟเวอร์ทำงานส่วนใหญ่ในการแสดงผลหน้าเว็บ จึงอาจต้องใช้ทรัพยากรเพิ่มเติมเพื่อรองรับคำขอหลายรายการ
โต้ตอบส่วนประกอบเซิร์ฟเวอร์
RSC เป็นฟีเจอร์ใน React ที่อนุญาตให้คอมโพเนนต์สามารถเรนเดอร์ทั้งหมดบนเซิร์ฟเวอร์:
- เซิร์ฟเวอร์ดึงข้อมูล
- เซิร์ฟเวอร์เรนเดอร์แอปพร้อมเนื้อหา
- ลูกค้าดาวน์โหลดทรัพยากร JS
- ภาวะขาดน้ำเกิดขึ้นในลูกค้า
หมายเหตุ: ส่วนประกอบเซิร์ฟเวอร์ถูกเรนเดอร์ทั้งหมดบนเซิร์ฟเวอร์ โดยจะไม่รวมอยู่ในบันเดิล JS และไม่ถูกไฮเดรต ดังนั้นขั้นตอนที่ 3 และ 4 จึงเกิดขึ้นกับส่วนประกอบของไคลเอ็นต์

ข้อดีของ RSC ป>
- การจัดการข้อมูลอย่างมีประสิทธิภาพ: การดึงข้อมูลจะถูกย้ายไปยังเซิร์ฟเวอร์ ใกล้กับฐานข้อมูลของคุณมากขึ้น สิ่งนี้ช่วยปรับปรุงประสิทธิภาพโดยการลบการส่งข้อมูลแบบไปกลับระหว่างไคลเอ็นต์-เซิร์ฟเวอร์
- ขนาด JavaScript ที่ลดลงบนไคลเอนต์ :เนื่องจาก React Server Components ไม่ส่ง JavaScript ใดๆ ไปยังไคลเอนต์ ขนาดบันเดิลโดยรวมจึงลดลง และปรับปรุงประสิทธิภาพ
- การโหลดหน้าเริ่มต้นเร็วขึ้น :คอมโพเนนต์การเรนเดอร์ล่วงหน้าบนเซิร์ฟเวอร์หมายความว่าไคลเอ็นต์ได้รับ HTML ที่เรนเดอร์เต็มรูปแบบเร็วขึ้น ซึ่งช่วยปรับปรุงเวลาในการใช้ First Contentful Paint (FCP)
- SEO ที่ได้รับการปรับปรุง :เนื้อหาได้รับการเรนเดอร์ฝั่งเซิร์ฟเวอร์อย่างสมบูรณ์ ทำให้เครื่องมือค้นหารวบรวมข้อมูลและจัดทำดัชนีเนื้อหาได้ง่ายขึ้น
ความท้าทายของ RSC ป>
- สถานะและวงจรการใช้งาน :React Server Components ไม่มีสิทธิ์เข้าถึง API ของเบราว์เซอร์ (เช่น
13,20รหัส> ) เนื่องจากมีการแสดงผลบนเซิร์ฟเวอร์ - ไม่มีการโต้ตอบฝั่งไคลเอ็นต์ :ส่วนประกอบเซิร์ฟเวอร์ React ไม่ได้มีไว้สำหรับการอัปเดตหรือการโต้ตอบแบบไดนามิก คุณต้องใช้คอมโพเนนต์ไคลเอ็นต์สำหรับส่วนโต้ตอบของแอปของคุณ
การใช้ส่วนประกอบเซิร์ฟเวอร์ React
โต้ตอบส่วนประกอบเซิร์ฟเวอร์ใน Next.js
ตามค่าเริ่มต้น Next.js ใช้ส่วนประกอบเซิร์ฟเวอร์ พวกมันถูกเรนเดอร์ด้วย 3 วิธีที่แตกต่างกัน:
- การแสดงผลแบบคงที่ (ค่าเริ่มต้น): เส้นทางจะแสดงในเวลา เวลาสร้าง หรือในเบื้องหลังหลังการตรวจสอบความถูกต้องของข้อมูลอีกครั้ง
- การแสดงผลแบบไดนามิก: เส้นทางจะแสดงผลสำหรับผู้ใช้แต่ละราย ณ เวลาที่ร้องขอ .
- สตรีมมิ่ง: UI ถูกเรนเดอร์จากเซิร์ฟเวอร์อย่างต่อเนื่อง
เมื่อใดที่คุณควรใช้ ส่วนประกอบเซิร์ฟเวอร์ React ?
คุณควรใช้ React Server Components เมื่อ :
- คุณมีเนื้อหาคงที่และไม่มีการโต้ตอบซึ่งไม่ได้เปลี่ยนแปลงบ่อย
- คุณต้องการปรับปรุงประสิทธิภาพโดยลด JavaScript ที่ส่งไปยังไคลเอนต์
- SEO มีความสำคัญต่อการสมัครของคุณ
- คุณต้องการถ่ายโอนงานการดึงข้อมูลหรือการคำนวณจำนวนมากไปยังเซิร์ฟเวอร์
คุณไม่ควรตอบสนองส่วนประกอบเซิร์ฟเวอร์เมื่อ :
- ส่วนประกอบของคุณต้องการการโต้ตอบ สถานะ หรือ hooks ฝั่งไคลเอ็นต์
- คุณต้องเข้าถึง API ของเบราว์เซอร์หรือต้องมีการอัปเดตแบบเรียลไทม์
- คุณกำลังสร้างเพจที่ซับซ้อนด้วยตรรกะฝั่งไคลเอ็นต์จำนวนมากหรือเนื้อหาเฉพาะผู้ใช้
ข้อผิดพลาดทั่วไป
องค์ประกอบของไคลเอ็นต์ไม่ได้แสดงผลทั้งหมดบนไคลเอ็นต์ ป>
แสดงผลทั้งบนไคลเอนต์และเซิร์ฟเวอร์ มีชื่อว่า Client Components เพื่อแยกความแตกต่างจาก Server Components
38รหัส> คำสั่งสำหรับการดำเนินการของเซิร์ฟเวอร์ ป>
ตามค่าเริ่มต้น Next.js จะใช้ Server Components ดังนั้นคุณไม่จำเป็นต้องระบุอะไรเลย หากคุณต้องการใช้ Client Components ให้เพิ่ม 43 คำสั่งในการประกาศขอบเขตระหว่างโมดูลเซิร์ฟเวอร์และไคลเอนต์ 57รหัส> เป็นคำสั่งที่แตกต่างไปจากเดิมอย่างสิ้นเชิงซึ่งใช้สำหรับ การทำงานของเซิร์ฟเวอร์ ซึ่งอยู่นอกเหนือขอบเขตของบล็อกโพสต์นี้
การตั้งค่าโครงการ
เราจะใช้เทมเพลตบล็อกจาก Vercel:
pnpm create next-app --example https://github.com/vercel/examples/tree/main/solutions/blog blog คุณสามารถเรียกใช้ตัวอย่างในเครื่องและดูว่ามีลักษณะอย่างไร:
cd blog
pnpm dev
มาติดตั้ง 60 กัน :
pnpm add @upstash/redis การตั้งค่าสภาพแวดล้อม
- ไปที่ Upstash Console → Redis และสร้างฐานข้อมูลใหม่:

- เลื่อนลงไปที่ส่วน REST API สลับไปที่
72แล้วคัดลอกตัวแปรสภาพแวดล้อมสำหรับขั้นตอนถัดไป:

- สร้าง
89ไฟล์และวางตัวแปรสภาพแวดล้อมของคุณ:
UPSTASH_REDIS_REST_URL=<YOUR_URL>
UPSTASH_REDIS_REST_TOKEN=<YOUR_TOKEN> ตั้งค่าองค์ประกอบมุมมอง
สร้าง 92 :
import { headers } from 'next/headers'
import { Redis } from "@upstash/redis"
const redis = Redis.fromEnv();
async function view(slug: string, ip: string) {
// Hash the IP address to anonymize it
const buf = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(ip));
const hash = Array.from(new Uint8Array(buf)).map((b) => b.toString(16).padStart(2, "0")).join("");
// Deduplicate views
const newView = await redis.set(`deduplicate:${hash}:${slug}`, true, {
nx: true, // Only set the key if it doesn't exist
ex: 24 * 60 * 60, // Expire the key after 24 hours
});
if (newView) {
await redis.incr(`pageviews:${slug}`); // Increment the view count
}
}
export default async function Views({ slug }: { slug: string }) {
// Get the IP address of the user
const header = headers()
const ip = (header.get('x-forwarded-for') ?? '127.0.0.1').split(',')[0]
// Increment the view count
await view(slug, ip)
// Get the view count
const views = await redis.get<number>(`pageviews:${slug}`) || 0
return (
<p className="text-sm text-neutral-600 dark:text-neutral-400">
{views} views
</p>
)
}
นำเข้าและแสดงส่วนประกอบมุมมอง
แก้ไข 109 :
...
import Views from 'app/components/views'
...
<div className="flex justify-between items-center mt-2 mb-8 text-sm">
<p className="text-sm text-neutral-600 dark:text-neutral-400">
{formatDate(post.metadata.publishedAt)}
</p>
<Views slug={post.slug} />
</div>
... ไปที่ http://localhost:3000/blog/vim เพื่อดูการทำงานของตัวนับการดู:

การเปรียบเทียบกับการตั้งค่าส่วนประกอบไคลเอนต์
ลองอ่านบล็อกโพสต์ของเรา "การเพิ่มตัวนับมุมมองในบล็อก Next.js ของคุณ" เพื่อดูการใช้งานกับส่วนประกอบของไคลเอ็นต์
นอกเหนือจากคุณประโยชน์อื่นๆ ที่กล่าวถึงในส่วนที่แล้ว โดยใช้ React Server Components:
- ลบความจำเป็นของ API ที่แยกต่างหาก
- ให้มุมมองแบบรวมที่เรียบง่ายของส่วนประกอบและตรรกะพร้อมประโยชน์ของการตรวจสอบประเภท
ปรับใช้
คุณสามารถปรับใช้เว็บไซต์ของคุณกับ Vercel ด้วยคำสั่งต่อไปนี้:
vercel คำสุดท้าย
ด้วยการรวมจุดแข็งของทั้งเซิร์ฟเวอร์และส่วนประกอบไคลเอนต์ คุณสามารถสร้างสมดุลที่เหมาะสมระหว่างประสิทธิภาพและการโต้ตอบในแอปพลิเคชันของคุณ ฉันหวังว่าคู่มือนี้จะช่วยให้คุณมีข้อมูลประกอบการตัดสินใจว่าเมื่อใดควรใช้ประโยชน์จาก React Server Components อย่างมีประสิทธิภาพ