Hiện đội ngũ phát triển của Next vẫn đang hoàn thiện các tính năng còn lại. Nên hướng dẫn này chỉ mang tính trải nghiệm và không nên sử dụng trong việc phát triển sản phẩm💥

React Server Components là loại component gì ? 🐶

Tôi sẽ chia component ra làm 2 loại là Server ComponentClient Component để tiện cho việc phân biệt công dụng của từng loại

Client component thì rất rõ ràng, nó chính là những component chỉ được sử dụng phía client

Còn Server component thì ngược lại, chỉ được sử dụng phía server, để hiểu rõ về nó chúng ta cần phải xem xét những khả năng mà RSC có thể và không thể làm. Dưới đây là những thứ mà RSC có thể làm:

  • ✔️ Truy cập các người dữ liệu như: functions, database
  • ✔️ Giảm kích thước dữ liệu trả về client
  • ✔️ Giảm số lượng request tới server
  • ✔️ Tối ưu trải nghiệm duyệt web của người dùng

Và không thể làm:

  • ❌ Không thể sử dụng useState hay useEffect
  • ❌ Không thể sử dụng được hook mà trong đó có sử dụng useState hoặc useEffect
  • ❌ Không thể sử dụng được Browser API

Lỗi sau sẽ hiển thị nếu bạn cố tình sử dụng các api trên

❌ RSC ko thể sử dụng useState, useEffect
❌ RSC ko thể sử dụng useState, useEffect (Xem ảnh gốc)

RSC và SSR khác nhau ra sao ? 💬

SSR là kĩ thuật được sử dụng để render ứng dụng ở phía server sau đó dữ liệu được render (HTML) sẽ được gửi xuống client, sau đó được browser đọc và hiển thị

RSC, như tôi đã đề cập trước đó, cũng được render ở phía server. Tuy nhiên, dữ liệu được render ra không phải là HTML. Dạng dữ liệu này được stream trực tiếp từ server tới client

Dữ liệu từ RSC
Dữ liệu từ RSC (Xem ảnh gốc)

Ngoài ra, RSC còn khác SSR ở 2 điểm sau

  • ✔️ RSC có thể render theo từng phần nhỏ, trong khi SSR thì render lại toàn bộ trang
  • ✔️ RSC có thể truy cập các nguồn dữ liệu từ database, không giống như SSR, chỉ có thể truy cập được các nguồn dữ liệu này thông qua getServerProps

Làm sao để dùng thử RSC 👨‍🚀

Để sử dụng được React Server Component thì bạn cần bật 2 option trong next.config.js như dưới đây

// next.config.js
module.exports = {
  experimental: {
    concurrentFeatures: true, // bật tính năng SSR Streaming
    serverComponents: true // bật tính năng React Server Components
  }
}

Giờ, để tạo ra 1 RSC thì bạn chỉ đơn giản là thay đổi tên file. Cụ thể như sau, pages/home.tsx đổi thành pages/home.server.tsx

Sử dụng RSC

Đầu tiên, chúng ta tọa 1 file pages/home.server.js và bổ sung 1 đoạn code đơn giản lấy dữ liệu như sau

// pages/home.server.js

import React from "react";
import ProfileDetail from "../components/ProfileDetail";

export default function Home() {
  return (
    <>
      <h2>Hello world</h2>
      <ProfileDetail />
    </>
  );
}

Tạo tiếp components/ProfileDetail.server.js, đây là nơi sự khác biệt giữa RSC và SSR

// components/ProfileDetail.server.js

import React from "react";
import { fetchData } from "../libs/fakeApi";

const resource = fetchData();

export default function ProfileDetail() {
  const user = resource.read();

  return (
    <div>
      <p>{user.username}</p>
      <h1>{user.email}</h1>
    </div>
  );
}

Và tạo thêm 1 file dùng để giả lập việc lấy dữ liệu (tôi đang giả định là mất 5s để dữ liệu được lấy về)

// libs/fakeApi.js

export function fetchData() {
  let status = "pending";
  let result;

  const pm = () =>
    new Promise((resolve, reject) => {
      fetch("https://jsonplaceholder.typicode.com/users/1")
        .then((res) => res.json())
        .then((json) => {
          setTimeout(() => {
            resolve(json);
          }, 5000); // tạm ngưng 5s để giả lập thời gian trả về
        })
        .catch((err) => {
          reject(err);
        });
    });

  let suspender = pm()
    .then((json) => {
      status = "success";
      result = json;
    })
    .catch((err) => {
      status = "error";
      result = err;
    });

  return {
    read() {
      if (status === "pending") {
        throw suspender;
      } else if (status === "error") {
        throw result;
      } else if (status === "success") {
        return result;
      }
    },
  };
}

Chạy thử thì kết quả sẽ được trả về sau 5s load dữ liệu.

Sử dụng RSC không có Suspend
Sử dụng RSC không có Suspend (Xem ảnh gốc)

Các bạn hãy để ý sự khác biệt khi sử dụng RSC ở đây. Đó là có thể truy cập dữ liệu từ components 👍

Điều này ko thể làm được khi sử dụng SSR hay Client Component 👎🏾

Sử dụng RSC với Suspend

Ở đoạn code trên, tôi đã đặt 1 khoảng thời gian delay là 5s. Điều này làm page phải đợi 5s để render ra được HTML. Tuy nhiên, nếu sử dụng <Suspend/> thì quá trình chờ đợi này sẽ được xử lý song song với quá trình render, hay nói cách khác là bất đồng bộ 👍

// pages/home.server.js

import React, { Suspense } from "react";
import ProfileDetail from "../components/ProfileDetail.server";

export default function Home() {
  return (
    <>
      <h2>Hello world</h2>
      <Suspense>
        <ProfileDetail />
      </Suspense>
    </>
  );
}

Reload lại trình duyệt, bạn sẽ thành dòng Hello world được load ra và sau 5s dữ liệu của <ProfileDetail/> sẽ được trả về

Sử dụng RSC với Suspend
Sử dụng RSC với Suspend (Xem ảnh gốc)

But, tại sao RSC lại giảm kích thước dữ liệu trả về client ?? 🐷

Tôi sẽ lấy 1 ví dụ, sư dụng moment để hiển thị thời gian hiện tại. Các bạn hãy tạo ra 2 file có cùng nội dung như bên dưới

// components/Time.server.js
// components/Time.client.js

import React from "react";
import moment from "moment";

export default function Time() {
  const time = moment().format("DD/MM/YYYY hh:mm");
  return <div>{time}</div>;
}

Sau đó thử import lần lượt từng file vào pages/home.server.js

// pages/home.server.js
....
export default function Home() {
  return (
    <>
      <h2>Hello world</h2>
      <Time />
      <Suspense>
        <ProfileDetail />
      </Suspense>
    </>
  );
}

Rồi lần lượt reload lại page để kiểm tra ta sẽ thấy sự khác biệt. Nếu sử dụng components/Time.server thì bạn sẽ không tìm thấy thư viện node_modules/moment. Điều này có nghĩa là kích thước dữ liệu đã được thu gọn lại

Server component
Server component (Xem ảnh gốc)

Còn nếu sử dụng components/Time.client thì ngược lại

Client component
Client component (Xem ảnh gốc)

Kết

Đến thời điểm hiện tại, RSC vẫn chưa release chính thức, tuy nhiên 1 số ưu điểm có nó thì rất đáng để mong đợi. KHUYẾN CÁO KHÔNG NÊN SỬ DỤNG RSC Ở MÔI TRƯỜNG PRODUCTION.

Cám ơn các bạn đã theo dõi hết bài viết