31/08/2018, 15:21

ReactJS: Tăng tốc độ đổ dữ liệu từ React-server

Nhắc đến React, chúng ta thường nghĩ đến một công cụ cho browser (đối với những người sử dụng React Native thì họ sẽ nghĩ đến một công cụ cho client). Nhưng số lượng sử dụng React render bên server ngày càng tăng (React-server) và hiện tại thì React khá là chậm trong khoản này nên làm ...

Nhắc đến React, chúng ta thường nghĩ đến một công cụ cho browser (đối với những người sử dụng React Native thì họ sẽ nghĩ đến một công cụ cho client). Nhưng số lượng sử dụng React render bên server ngày càng tăng (React-server) và hiện tại thì React khá là chậm trong khoản này nên làm sao tăng tốc độ gửi HTML cho người dùng để tăng trải nghiệm web cũng là một điều các dev đang quan tâm. Trong video demo của tác giả Sasha Aickin, ông có một ví dụ nhỏ để test benchmark (mục đích của bài viết chỉ là tổng kết lại những kết luận của tác giả mà không đi sâu vào test nên bạn chịu khó xem video để biết thêm chi tiết). Tác giả tạo một demo bắt React đổ khoảng 900 KBs ra server và gửi về client và sử dụng benchmarkjs để test. Ở lần thử đầu tiên thì tác giả thử với cmd:

và mất khoảng 1025ms để hoàn thành load HTML. Có 3 nguyên nhân chính dẫn đến việc giảm hiệu năng của React-server:

  • renderToStrings (method trong React-server để đổ dữ liệu) chạy trên một thread (synchronous) nên nhiều CPU core không giúp cho việc chạy function này nhanh hơn.
  • Client render và Server render giống nhau ( mặc dù điểm cộng là code sẽ dễ đọc hơn nhưng điểm trừ lớn là sự khác biệt giữa server và client side như React-server vẫn phải theo dõi virtual DOM và event trong khi việc này rất vô nghĩa và tốn dung lượng )
  • Facebook không sử dụng cho production (=)) chắc tụi nó thấy chậm quá)

Sau đây là 6 mánh có thể giúp bạn cải thiện hiệu suất của React-server một cách tối đa.

1. PRODUCTION MODE

Đổi

thành

Đơn giản như thế thôi. Bạn có thể thấy ở đây, tốc độ load về còn 263 ms, hiệu năng tăng khoảng 4 lần. Tại sao nhỉ?

Trong development mode, React rất chu đáo trong việc cung cấp cho bạn hệ thống báo lỗi khá tốt nhưng chính điều này làm chậm quá trình đổ dữ liệu nên khi chuyển sang production mode, toàn bộ hệ thống này sẽ không được sử dụng nên hiệu suất tăng là điều hiển nhiên.

2. Sử dụng bản min cho browser

Việc này đơn giản nhưng lại đem lại hiệu quả cũng tương đối (được ít nào hay ít đấy). Trong video, sau khi tác giả sử dụng bản thu gọn (min version) thì tốc độ load giảm khoảng 70ms ( trung bình trong các test khác của tác giả thì hiệu suất tăng khoảng 30%). Vì lý do gì đó mà node luôn kiểm tra xem app của chúng ta có chạy production mode(process.env.NODE_ENV) không và việc này rất tốn kém (khoảng 1/3 thời gian load). Rất nhiều người đã báo bug này lên React-server nên mong là trong thời gian không xa bug sẽ được fix. Lưu ý là sử dụng cách này cho production mode thôi nhé không dùng cho development mode, không là sẽ rất khó để debug.

3. Babels transforms

React bản 14. có thêm hai tính tăng quan trọng là Constant Elements và Inline Elements.

Constant Elements tìm component được khai báo dưới dạng const trong JSX, đẩy nó lên đầu tiên (hoist), gán vào biến khác và sử dụng luôn biến đó nên mỗi lần render React sẽ không phải tạo lại từ đầu.

Ví dụ trong trường hợp ta tạo một component như sau:

Constant Elements sẽ kéo nó ra ngoài như sau:

Giờ khi chạy render, React Component sẽ không phải tạo lại một class mới nữa.

Inline Elements loại bỏ hoàn toàn việc gọi React.createElement và thay vào bằng literal object để giảm thiểu việc tạo lại element mỗi khi render. Nó thay thế object

thành

(nhìn đã thấy hoa cả mắt nhưng may bạn không cần phải nhớ làm gì).

Chỉ việc:

và thêm vào Babel config:

Voilà. Tốc độ load còn 173ms (thường giảm khoảng 10%).

4. Tránh sử dụng createClass

Component được tạo bởi React.createClass chậm hơn sử dụng ES6 class và stateless components rất nhiều.

Thay vì

nên đổi thành

Trong demo, tốc độ load giảm còn 66ms. (Khả năng autobind của React.createClass có vấn đề)

5. Streaming

Việc browser xử lý càng ngày càng tốt data stream tạo điều kiện tốt hơn cho server khi truyền tải dữ liệu cũng như tạo trải nghiệm tốt hơn cho người dùng. Bạn có thể tìm hiểu thêm qua “Chunked Encoding” trong HTTP/1.1(1999).

React-dom chỉ có method renderToString trả về String sau khi đã render đầy đủ nên tác giả đã tạo react-dom-stream. Khi sử dụng react-dom-stream, thời gian gửi stream data sẽ như nhau kể cả khi nội dung dài hơn.

Chỉ cần đổi

thành

và đổi tất cả renderToString thành

Ở đây, byte đầu tiên được gửi chỉ sau 4ms, byte cuối được gửi sau 62ms. Lưu ý nhỏ ở đây là cách này mới đang trong giai đoạn beta, không nên sử dụng trong production mode (trừ khi bạn thích thì bạn có thể làm để tự tạo điểm nhấn thôi).

6. Cache Components

Các component trong React chỉ bao gồm props và state sau đó được đổ ra String nên việc cache ở server là hoàn toàn có thể.

Đầu tiên là install react-dom-stream@beta qua npm, thêm cache object vào renderToString

Thêm một method như sau:

Việc cache mà không có key rất nguy hiểm vì React sẽ không biết component nào để cache.

Sau demo, tốc độ load còn 5ms. Mặc dù đây là trường hợp tối ưu(best case scenario) tức là toàn bộ component là không đổi (immutable) nhưng ý tưởng này cũng khá hay. Điểm trừ là

  • đây mới chỉ là alpha, chưa được thử trong production
  • nếu bạn cache quá nhiều thứ khác nhau thì nó cũng chả khác với việc không cache là mấy
  • cache mà nhầm 1 key thì data của bạn có thể đưa cho nhầm người (trong một lần backup lại server, steam đã gửi nhầm cache page có tài khoản ngân hàng của một khách hàng cho một khách hàng khác)

Tổng hợp

Production Mode: YES!

Minified React: YES!

Babel Trasnform: YES!

ES6 Classes & Stateless Components: YES!

Steaming: Tùy.

Cache: Thử thôi nhé.

Techtalk via Techmaster

0