0
0
Lập trình
Flame Kris
Flame Krisbacodekiller

🚀 Tăng Tốc Docusaurus Với MSW: Giả Lập API Cho Tài Liệu Tương Tác

Đăng vào 3 ngày trước

• 7 phút đọc

Tăng Tốc Docusaurus Với MSW: Giả Lập API Cho Tài Liệu Tương Tác

Khi bạn xây dựng tài liệu cho một API hoặc sản phẩm phụ thuộc vào dữ liệu từ backend, bạn sẽ đối mặt với một thách thức quen thuộc: làm thế nào để làm cho các ví dụ của bạn cảm thấy thực tế mà không phụ thuộc vào một môi trường staging dễ bị tổn thương hoặc phơi bày các điểm cuối sản xuất?

Bài viết này không chỉ là một tập hợp các đoạn mã — nó là một hướng dẫn chi tiết và sâu sắc về cách sử dụng 🛠 Mock Service Worker (MSW) với 📚 Docusaurus. Cuối bài, bạn sẽ biết không chỉ cách thiết lập nó mà còn nhiều điều khác.

💡 Tại Sao Tài Liệu Cần Phản Hồi API Thực Tế

Bạn đã bao giờ theo dõi một hướng dẫn API, nhấn “Chạy” và ngay lập tức gặp lỗi? ❌ Có thể máy chủ staging đã ngừng hoạt động. Có thể bạn không có mã thông báo xác thực đúng. Có thể dữ liệu trông… nhàm chán.

Người đọc của bạn cũng cảm thấy điều này.

Bằng cách giả lập API của bạn, bạn:

  • Đảm Bảo Tính Nhất Quán: Dữ liệu trong các ví dụ của bạn luôn khớp với tài liệu.
  • 🧪 Cung Cấp Một Sandbox An Toàn: Người đọc có thể thử nghiệm với các mẫu mã mà không làm hỏng bất cứ điều gì.
  • Giảm Rào Cản Gia Nhập: Không cần mã xác thực, VPN hay bước thiết lập nào — chỉ cần chạy npm start.
  • ✈️ Cho Phép Làm Việc Ngoại Tuyến: Các cộng tác viên có thể làm việc từ máy bay, tàu hỏa hoặc bất kỳ đâu mà không cần internet.

MSW chặn các yêu cầu ở lớp mạng (Service Worker), có nghĩa là frontend của bạn không biết sự khác biệt giữa API thực và giả — hoàn hảo cho tài liệu tương tác.

🏗 Bước 1: Cài Đặt MSW — Nền Tảng

Đầu tiên, bạn cần cài đặt MSW như một phụ thuộc phát triển:

Copy
npm install msw --save-dev

Điều này thêm công cụ cốt lõi mà bạn cần để khởi động một Service Worker trong môi trường phát triển.

🗂 Bước 2: Thiết Kế Kiến Trúc Giả Lập

Trước khi viết mã, hãy suy nghĩ về kiến trúc:

  • Handlers: Định nghĩa từng điểm cuối bạn muốn giả lập.
  • Browser Worker: Khởi động MSW trong trình duyệt.
  • Node Server (Tùy Chọn): Cho phép bạn tái sử dụng cùng một bộ giả lập trong các bài kiểm tra.

Tạo một cấu trúc thư mục như sau:

Copy
my-docusaurus-app/
├── src/
│   ├── mocks/
│   │   ├── handlers.js  ← định nghĩa điểm cuối
│   │   └── browser.js   ← khởi động MSW
│   └── theme/
│       └── Root.js      ← khởi động MSW trong chế độ phát triển

Cấu trúc này làm rõ cho các cộng tác viên tương lai nơi mà logic giả lập sống.

✍️ Bước 3: Viết Handler Đầu Tiên

Hãy nghĩ về một handler như là một hợp đồng API thu nhỏ — nó chỉ định phương thức HTTP nào, điểm cuối nào và phản hồi nào sẽ được trả về.

javascript Copy
// src/mocks/handlers.js
import { rest } from 'msw';

export const handlers = [
  rest.get('/api/info', (req, res, ctx) => {
    return res(
      ctx.status(200),
      ctx.json({
        message: 'Xin chào từ MSW! Đây là một phản hồi ổn định, có thể dự đoán.'
      })
    );
  }),
  rest.post('/api/login', async (req, res, ctx) => {
    const { username } = await req.json();
    return res(
      ctx.status(200),
      ctx.json({ token: `fake-jwt-token-for-${username}` })
    );
  })
];

Điều này giúp cho việc tái tạo các luồng đăng nhập hoặc các yêu cầu fetch mà không cần một backend đang hoạt động trở nên dễ dàng.

🌐 Bước 4: Khởi Động MSW Trong Trình Duyệt

Tạo src/mocks/browser.js:

javascript Copy
import { setupWorker } from 'msw';
import { handlers } from './handlers';

export const worker = setupWorker(...handlers);

Tệp này kết nối tất cả các handlers và tạo một điểm vào duy nhất cho Service Worker.

🏃 Bước 5: Khởi Động Worker Trong Docusaurus

Chúng ta muốn MSW chạy tự động khi tài liệu được tải trong chế độ phát triển. Docusaurus cung cấp một cách để bọc toàn bộ ứng dụng qua Root.js.

javascript Copy
// src/theme/Root.js
import React, { useEffect } from 'react';

export default function Root({ children }) {
  useEffect(() => {
    if (process.env.NODE_ENV === 'development') {
      import('../mocks/browser').then(({ worker }) => {
        worker.start({ onUnhandledRequest: 'bypass' });
      });
    }
  }, []);

  return <>{children}</>;
}

Tại sao lại là onUnhandledRequest: 'bypass'? Điều này đảm bảo rằng các yêu cầu chưa được giả lập vẫn đến API thực, điều này hữu ích nếu bạn chỉ đang giả lập một phần của backend.

🎨 Bước 6: Làm Cho Tài Liệu Tương Tác

Dưới đây là một ví dụ về thành phần React mà lấy dữ liệu từ điểm cuối giả lập của chúng ta:

javascript Copy
import React, { useEffect, useState } from 'react';

export default function ExampleComponent() {
  const [data, setData] = useState(null);

  useEffect(() => {
    fetch('/api/info')
      .then((res) => res.json())
      .then(setData);
  }, []);

  return (
    <div style={{ background: '#f8f8f8', padding: '1rem', borderRadius: '8px' }}>
      <h4>Phản Hồi API Giả Lập</h4>
      <pre>{JSON.stringify(data, null, 2)}</pre>
    </div>
  );
}

Điều này tạo ra một thành phần sống động ngay trong tài liệu của bạn, để người đọc có thể thấy các phản hồi thực tế như chúng sẽ xuất hiện trong một ứng dụng thực sự.

🏗 Xử Lý Triển Khai Trên GitLab Pages (URL Động)

Một thách thức mà tôi đã gặp phải sau khi tích hợp MSW là triển khai tài liệu trên GitLab Pages. Mỗi lần chạy pipeline tạo ra một URL động như:

Copy
https://myproject.gitlab.io/-/jobs/235345/artifacts/public/index.html

Theo mặc định, MSW tìm kiếm mockServiceWorker.js tại gốc (/mockServiceWorker.js). Trên GitLab Pages với các URL động, điều này đã bị hỏng vì Service Worker nằm ở:

Copy
https://myproject.gitlab.io/-/jobs/235345/artifacts/mockServiceWorker.js

Giải Pháp

Khi gọi worker.start(), bạn có thể truyền một tùy chọn serviceWorker.url để cho MSW biết chính xác nơi tìm tệp:

javascript Copy
worker.start({
  serviceWorker: {
    url: `${window.location.pathname.replace(/\/index\.html$/, '')}/mockServiceWorker.js`
  }
});

Điều này tính toán động URL chính xác dựa trên đường dẫn của trang hiện tại, đảm bảo MSW luôn được tìm thấy bất kể lần chạy pipeline.

Sửa đổi nhỏ này đã làm cho việc triển khai GitLab Pages trở nên đáng tin cậy và bền vững, vì mỗi lần pipeline tạo ra một trang tài liệu tương tác hoàn toàn chức năng.

Bước 7: Những Cạm Bẫy Thường Gặp Và Cách Tránh Chúng

  1. Lỗi CORS: Đảm bảo rằng URL giả lập của bạn khớp chính xác với những gì fetch đang yêu cầu (bao gồm cả miền).
  2. Worker Không Khởi Động: Quên import browser.js trong Root.js có nghĩa là MSW không bao giờ chạy.
  3. Xây Dựng Sản Xuất Bị Hỏng: Bảo vệ khởi động MSW với NODE_ENV để nó chỉ chạy cục bộ.
  4. Đường Dẫn Động Trên CI/CD: Sử dụng serviceWorker.url để chỉ định MSW đến vị trí chính xác trong các triển khai CI/CD.

Phía Sau Phát Triển: Sử Dụng MSW Trong Các Bài Kiểm Tra

Một trong những siêu năng lực của MSW là bạn có thể tái sử dụng những mock này trong các bài kiểm tra tích hợp:

javascript Copy
import { setupServer } from 'msw/node';
import { handlers } from './handlers';

const server = setupServer(...handlers);

beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());

Bây giờ, các bài kiểm tra của bạn, môi trường phát triển cục bộ và tài liệu của bạn đều nói cùng một ngôn ngữ.

Kết Luận

Giả lập APIs trong trang Docusaurus của bạn không chỉ là một thủ thuật, nó là một yếu tố chuyên nghiệp giúp tài liệu tuyệt vời trở nên nổi bật. Bằng cách sử dụng MSW, bạn nhận được phản hồi giống như sản xuất mà không gặp phải những đau đầu giống như sản xuất. Người dùng của bạn học nhanh hơn và nhóm của bạn dành ít thời gian hơn cho việc xử lý tài liệu.

Các Thực Hành Tốt Nhất

  • Giữ cho các mock của bạn đơn giản và rõ ràng.
  • Thường xuyên kiểm tra để đảm bảo các phản hồi giả lập khớp với API thực tế.

Câu Hỏi Thường Gặp (FAQ)

1. MSW có tương thích với tất cả các framework không?
Có, MSW có thể được sử dụng với hầu hết các framework frontend.
2. Tôi có thể sử dụng MSW trong môi trường sản xuất không?
Không nên. MSW chủ yếu được thiết kế cho môi trường phát triển và kiểm tra.

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào