Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Redis

สร้าง Real-Time View Counter ด้วย React Server Components

ในบทช่วยสอนนี้ เราจะเข้าใจ React Server Components และด้วยความรู้นั้น สร้าง view counter เรียบง่ายสำหรับแอปของคุณด้วยกัน ไม่ว่าจะข้ามไปที่ Project Setup ได้เลยถ้าคุณอยากดำเนินการ implement ทันที

การเข้าใจ React Server Components

เพื่อเข้าใจว่า React Server Components ทำงานอย่างไร เราจะดู Client-Side Rendering (CSR) และ Server-Side Rendering (SSR) แบบสั้นๆ

Client-Side Rendering (CSR)

ใน CSR ส่วนใหญ่ของการ rendering เกิดขึ้นใน browser ฝั่ง client:

  1. User request ไซต์
  2. Server ส่ง HTML file และลิงก์ไปยัง CSS และ JS files
  3. Client ดาวน์โหลด JS resources
  4. Client render หน้าโดยไม่มีเนื้อหา
  5. Client fetch ข้อมูลจาก API ใน Server
  6. Client re-render หน้าพร้อมเนื้อหา

สร้าง Real-Time View Counter ด้วย React Server Components

Server-Side Rendering (SSR)

ใน SSR เซิร์ฟเวอร์สร้าง HTML content เต็มรูปแบบสำหรับแต่ละ request และส่งไปยัง client:

  1. User request ไซต์
  2. Server render HTML files จริง แต่ยังไม่ interactive
  3. Client ดาวน์โหลด JS resources
  4. ใน Client ใช้ฟังก์ชัน hydrateRoot() เพื่อ attach event listeners, state และ interactivity อื่นๆ ของ React components ไปยัง DOM elements ที่มีอยู่ซึ่งถูกสร้างโดย Server กระบวนการนี้รู้จักในชื่อ hydration
  5. Client fetch ข้อมูลจาก API ใน Server
  6. Client re-render หน้าพร้อมเนื้อหา

สร้าง Real-Time View Counter ด้วย React Server Components

ข้อได้เปรียบของ SSR

  • Better SEO: เพราะ search engine crawlers อ่าน fully-rendered HTML ได้ SSR จึงเป็น SEO-friendly
  • Faster initial load: เนื่องจาก HTML content เต็มรูปแบบถูก render และส่งจาก server ผู้ใช้เห็นเนื้อหาหน้าได้เร็ว

ข้อเสียของ SSR

  • Slower navigation: แต่ละ request หน้าใหม่ต้องการ round-trip communication สำหรับ full reload ของ HTML จาก server
  • Increased server load: เนื่องจาก server ทำงานส่วนใหญ่ในการ render หน้า อาจต้องการทรัพยากรมากขึ้นเพื่อจัดการ multiple requests

React Server Components (RSC)

RSC เป็นฟีเจอร์ใน React ที่อนุญาตให้ components ถูก render ทั้งหมดบน server:

  1. Server fetch ข้อมูล
  2. Server render app พร้อมเนื้อหา
  3. Client ดาวน์โหลด JS resources
  4. Hydration เกิดขึ้นใน Client

หมายเหตุ: Server components ถูก render ทั้งหมดบน server พวกมันไม่ได้รวมอยู่ใน JS bundle และไม่ได้ถูก hydrate ดังนั้นขั้นตอน 3 และ 4 เกิดขึ้นสำหรับ Client components

สร้าง Real-Time View Counter ด้วย React Server Components

ข้อได้เปรียบของ RSC

  • Efficient Data Handling: การดึงข้อมูลย้ายไปที่ server ใกล้ database ของคุณมากขึ้น นี่ปรับปรุงประสิทธิภาพโดยการลบ client-server round trip
  • Reduced JavaScript Size on the Client: เนื่องจาก React Server Components ไม่ส่ง JavaScript ไปที่ client ขนาด bundle ทั้งหมดลดลง ปรับปรุงประสิทธิภาพ
  • Faster Initial Page Load: การ pre-render components บน server หมายถึง client ได้รับ fully-rendered HTML เร็วขึ้น ปรับปรุง time to First Contentful Paint (FCP)
  • Improved SEO: เนื้อหาถูก render ทั้งหมดฝั่ง server ทำให้ search engines crawl และ index เนื้อหาง่ายขึ้น

ความท้าทายของ RSC

  • State and Lifecycle: React Server Components ไม่มีการเข้าถึง browser APIs (เช่น useState, useEffect) เนื่องจากถูก render บน server
  • No Client-Side Interactivity: React Server Components ไม่ได้สำหรับ dynamic updates หรือ interactivity คุณต้องใช้ Client Components สำหรับส่วน interactive ของแอปของคุณ

การใช้ React Server Components

React Server Components ใน Next.js

โดย default Next.js ใช้ Server Components พวกมันถูก render 3 วิธีที่แตกต่างกัน:

  • Static Rendering (Default): routes ถูก render ที่ build time หรือใน background หลัง data revalidation
  • Dynamic Rendering: routes ถูก render สำหรับแต่ละ user ที่ request time
  • Streaming: UI ถูก render แบบ progressive จาก server

เมื่อไหร่ควรใช้ React Server Components?

คุณควรใช้ React Server Components เมื่อ:

  • คุณมี static, non-interactive content ที่ไม่เปลี่ยนบ่อย
  • คุณอยากปรับปรุงประสิทธิภาพโดยการลด JavaScript ที่ส่งไปที่ client
  • SEO สำคัญสำหรับแอปพลิเคชันของคุณ
  • คุณอยาก offload heavy data-fetching หรือ computational tasks ไปที่ server

คุณไม่ควรใช้ React Server Components เมื่อ:

  • Components ของคุณต้องการ client-side interactivity, state, หรือ hooks
  • คุณต้องการเข้าถึง browser APIs หรือต้องการ real-time updates
  • คุณกำลังสร้างหน้าที่ซับซ้อนพร้อม heavy client-side logic หรือ user-specific content

Common Pitfalls

Client Components ไม่ได้ถูก render ทั้งหมดบน Client

พวกมันถูก render ทั้งบน Client และ Server พวกมันถูก命名ว่า Client Components เพื่อแยกจาก Server Components

‘use server’ directive เป็นสำหรับ Server Actions

โดย default Next.js ใช้ Server Components ดังนั้นคุณไม่ต้องระบุอะไร หากคุณอยากใช้ Client Components คุณเพิ่ม directive ‘use client’ เพื่อประกาศ boundary ระหว่าง Server และ Client modules ‘use server’ เป็น directive ที่ต่างกันโดยสิ้นเชิงใช้สำหรับ Server Actions ซึ่งอยู่นอกขอบเขตของบล็อกโพสต์นี้

Project Setup

เราจะใช้ Blog template จาก Vercel:

pnpm create next-app --example https://github.com/vercel/examples/tree/main/solutions/blog blog

คุณสามารถรันตัวอย่างใน local ได้และดูว่ามันเป็นอย่างไร:

cd blog pnpm dev

มาติดตั้ง @upstash/redis:

pnpm add @upstash/redis

Environment Setup

  1. ไปที่ Upstash Console → Redis และสร้าง Database ใหม่:

สร้าง Real-Time View Counter ด้วย React Server Components

  1. เลื่อนลงไปที่ส่วน REST API สลับไปที่แท็บ .env และคัดลอก environment variables สำหรับขั้นตอนถัดไป:

สร้าง Real-Time View Counter ด้วย React Server Components

  1. สร้างไฟล์ .env และวาง environment variables ของคุณ:
UPSTASH_REDIS_REST_URL=<YOUR_URL> UPSTASH_REDIS_REST_TOKEN=<YOUR_TOKEN>

Setup Views Component

สร้าง /app/components/views.tsx:

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> ) } 

Import และ Display Views Component

แก้ไข /app/blog/[slug]/page.tsx:

... 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> ...

ไปที่ https://localhost:3000/blog/vim เพื่อดู view counter ทำงาน:

สร้าง Real-Time View Counter ด้วย React Server Components

เปรียบเทียบกับ Client Components Setup

ดูบล็อกโพสต์ "Adding a View Counter to your Next.js Blog" เพื่อดู implementation ด้วย Client Components

พร้อมกับข้อได้เปรียบอื่นๆ ที่กล่าวไว้ในส่วนก่อนหน้า การใช้ React Server Components:

  • ลบความจำเป็นของ API แยกต่างหาก
  • ให้มุมมองที่ unified และเรียบง่ายของ component และ logic ของมัน พร้อมข้อได้เปรียบของ type checking

Deploy

คุณสามารถปรับใช้ไซต์ของคุณไปที่ Vercel ด้วยคำสั่งต่อไปนี้:

vercel

Final Words

ด้วยการรวมจุดแข็งของทั้ง Server และ Client Components คุณสามารถสร้างสมดุลที่เหมาะสมระหว่างประสิทธิภาพและ interactivity ในแอปพลิเคชันของคุณได้ หวังว่าคู่มือนี้จะช่วยให้คุณตัดสินใจได้อย่างมีข้อมูลเมื่อควรใช้ React Server Components อย่างมีประสิทธิภาพ