Các tuyến đường kết xuất trước có React-snap

Không kết xuất phía máy chủ nhưng vẫn muốn tăng tốc hiệu suất của trang web React? Hãy thử kết xuất trước!

react-snap là một thư viện bên thứ ba giúp kết xuất trước các trang trên trang web của bạn thành tệp HTML tĩnh. Điều này có thể cải thiện thời gian Vẽ lần đầu trong ứng dụng của bạn.

Dưới đây là thông tin so sánh về cùng một ứng dụng có và không có tính năng kết xuất trước được tải trên một kết nối 3G mô phỏng và thiết bị di động:

So sánh quá trình tải song song. Phiên bản sử dụng tính năng kết xuất trước tải nhanh hơn 4,2 giây.

Tại sao thông tin này hữu ích?

Vấn đề chính về hiệu suất của các ứng dụng trang đơn lớn là người dùng cần phải đợi(các) gói JavaScript tạo nên trang web hoàn tất quá trình tải xuống trước khi có thể xem nội dung thực. Gói càng lớn, người dùng càng phải chờ lâu.

Để giải quyết vấn đề này, nhiều nhà phát triển sử dụng phương pháp kết xuất ứng dụng trên máy chủ thay vì chỉ khởi động ứng dụng trên trình duyệt. Với mỗi lần chuyển đổi trang/tuyến, HTML hoàn chỉnh sẽ được tạo trên máy chủ và gửi đến trình duyệt, giúp giảm thời gian Vẽ lần đầu nhưng phải trả giá bằng Thời gian cho byte đầu tiên chậm hơn.

Xử lý trước là một kỹ thuật riêng biệt ít phức tạp hơn so với việc kết xuất máy chủ, nhưng cũng cung cấp một cách để cải thiện thời gian Vẽ lần đầu trong ứng dụng. Trình duyệt không có giao diện người dùng (headless browser) được dùng để tạo các tệp HTML tĩnh của mọi tuyến trong thời gian xây dựng. Sau đó, bạn có thể vận chuyển các tệp này cùng với các gói JavaScript cần thiết cho ứng dụng.

react-snap

react-snap sử dụng Puppeteer để tạo các tệp HTML được kết xuất trước của nhiều tuyến trong ứng dụng. Để bắt đầu, hãy cài đặt thư viện này dưới dạng phần phụ thuộc phát triển:

npm install --save-dev react-snap

Sau đó, hãy thêm tập lệnh postbuild vào package.json:

"scripts": {
  //...
  "postbuild": "react-snap"
}

Thao tác này sẽ tự động chạy lệnh react-snap mỗi khi tạo một bản dựng mới của ứng dụng (npm build).

Việc cuối cùng bạn cần làm là thay đổi cách khởi động ứng dụng. Thay đổi tệp src/index.js thành nội dung sau:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';

ReactDOM.render(<App />, document.getElementById('root'));
const rootElement = document.getElementById("root");

if (rootElement.hasChildNodes()) {
  ReactDOM.hydrate(<App />, rootElement);
} else {
  ReactDOM.render(<App />, rootElement);
}

Thay vì chỉ sử dụng ReactDOM.render để hiển thị phần tử React gốc trực tiếp vào DOM, phương thức này sẽ kiểm tra xem có nút con nào hiện diện hay không để xác định xem nội dung HTML đã được kết xuất trước hay chưa (hoặc đã được kết xuất trên máy chủ). Trong trường hợp đó, ReactDOM.hydrate được dùng để đính kèm trình nghe sự kiện vào HTML đã tạo thay vì tạo lại trình nghe sự kiện.

Giờ đây, việc tạo ứng dụng sẽ tạo các tệp HTML tĩnh dưới dạng tải trọng cho mỗi tuyến được thu thập thông tin. Bạn có thể xem tải trọng HTML bằng cách nhấp vào URL của yêu cầu HTML, sau đó nhấp vào thẻ Bản xem trước trong Công cụ cho nhà phát triển Chrome.

So sánh trước và sau. Ảnh chụp sau khi kết xuất cho thấy nội dung đã kết xuất.

Nội dung không được định kiểu xuất hiện chớp nhoáng

Mặc dù HTML tĩnh hiện được hiển thị gần như tức thì, nhưng theo mặc định, HTML tĩnh vẫn chưa được định kiểu. Điều này có thể gây ra vấn đề hiển thị "nội dung không được định kiểu" (FOUC). Điều này có thể đặc biệt đáng chú ý nếu bạn đang sử dụng thư viện CSS-in-JS để tạo bộ chọn vì gói JavaScript sẽ phải hoàn tất quá trình thực thi trước khi có thể áp dụng bất kỳ kiểu nào.

Để ngăn chặn điều này, bạn có thể trực tiếp đưa CSS quan trọng hoặc lượng CSS tối thiểu cần thiết để hiển thị trang ban đầu vào <head> của tài liệu HTML. react-snap sử dụng một thư viện bên thứ ba khác trong phần nội dung, minimalcss, để trích xuất mọi CSS quan trọng cho các tuyến khác nhau. Bạn có thể bật tính năng này bằng cách chỉ định nội dung sau trong tệp package.json:

"reactSnap": {
  "inlineCss": true
}

Giờ đây, khi xem trước phản hồi trong Công cụ của Chrome cho nhà phát triển, bạn sẽ thấy trang được tạo kiểu với CSS quan trọng được nội tuyến.

So sánh trước và sau. Ảnh chụp sau khi chạy cho thấy nội dung đã hiển thị và được tạo kiểu nhờ CSS quan trọng nội tuyến.

Kết luận

Nếu bạn không kết xuất các tuyến phía máy chủ trong ứng dụng, hãy sử dụng react-snap để kết xuất trước HTML tĩnh cho người dùng.

  1. Cài đặt thư viện này dưới dạng phần phụ thuộc phát triển và bắt đầu bằng các chế độ cài đặt mặc định.
  2. Sử dụng tuỳ chọn inlineCss thử nghiệm để chèn CSS quan trọng vào cùng dòng nếu tuỳ chọn này hoạt động cho trang web của bạn.
  3. Nếu bạn đang sử dụng tính năng phân tách mã ở cấp thành phần trong bất kỳ tuyến đường nào, hãy cẩn thận để không hiển thị trước trạng thái tải cho người dùng. react-snap README trình bày chi tiết hơn về vấn đề này.