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

Bạn không hiển thị 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 của bên thứ ba có chức năng kết xuất trước các trang trên trang web của bạn thành các tệp HTML tĩnh. Điều này có thể cải thiện thời gian Hiển thị đầu tiên trong ứng dụng của bạn.

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

Một thông tin so sánh về quá trình tải cạnh nhau. 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 tính năng này hữu ích?

Vấn đề chính về hiệu suất với các ứng dụng trang đơn lớn là người dùng 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 họ có thể thấy bất kỳ nội dung thực sự nào. Các gói càng lớn thì người dùng càng phải chờ lâu hơn.

Để 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 đường, HTML hoàn chỉnh sẽ được tạo trên máy chủ và gửi tới trình duyệt, giúp giảm thời gian Hiển thị đầu tiên nhưng sẽ phải trả chậm hơn Thời gian cho byte đầu tiên.

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

phản ứng-bật-tắt

react-snap sử dụng Puppeteer để tạo các tệp HTML được kết xuất trước gồm các tuyến khác nhau trong ứng dụng của bạn. Để bắt đầu, hãy cài đặt thư viện này dưới dạng một 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 có một bản dựng mới của ứng dụng được tạo (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 như 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 để kết xuất phần tử React gốc trực tiếp vào DOM, quy trình này sẽ kiểm tra xem đã có nút con nào hay chưa nhằm xác định xem nội dung HTML có được kết xuất trước (hoặc hiển thị trên máy chủ) hay không. Nếu đúng như vậy, ReactDOM.hydrate sẽ được dùng để đính kèm trình nghe sự kiện vào HTML đã tạo thay vì tạo lại HTML đó.

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

So sánh trước và sau. Cảnh quay sau cho thấy nội dung đã kết xuất.

Flash của nội dung không được định kiểu

Mặc dù HTML tĩnh hiện được hiển thị gần như ngay lập tức, 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 sự cố hiển thị "flash nội dung chưa đượ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 các 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.

Để giúp ngăn chặn điều này, CSS quan trọng hoặc lượng CSS tối thiểu cần thiết cho trang ban đầu hiển thị, có thể được đưa trực tiếp 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, 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, bạn có thể xem trước phản hồi trong Công cụ của Chrome cho nhà phát triển để hiển thị trang được tạo kiểu có cùng dòng CSS quan trọng.

So sánh trước và sau. Cảnh quay sau cho thấy nội dung đã kết xuất và được tạo kiểu do CSS quan trọng cùng dòng.

Kết luận

Nếu bạn không phải là các tuyến hiển thị 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 phần này dưới dạng phần phụ thuộc phát triển và bắt đầu chỉ với các tuỳ chọn 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 phương án này phù hợp với trang web của bạn.
  3. Nếu bạn đang sử dụng tính năng chia tách mã ở cấp thành phần trong bất kỳ tuyến nào, hãy cẩn thận không kết xuất trước trạng thái tải cho người dùng. react-snap README sẽ giải thích chi tiết hơn về vấn đề này.