Nghiên cứu điển hình thực tế về hoạt động tối ưu hoá hiệu suất của React SPA.
Hiệu suất trang web không chỉ ảnh hưởng đến thời gian tải. Điều quan trọng là phải cung cấp trải nghiệm nhanh và thích ứng cho người dùng, đặc biệt là đối với các ứng dụng cải thiện hiệu suất mà mọi người sử dụng hằng ngày. Nhóm kỹ thuật tại Recruit Technologies đã trải qua một dự án tái cấu trúc để cải thiện một trong các ứng dụng web của họ, AirSHIFT, nhằm nâng cao hiệu suất từ hoạt động đầu vào của người dùng. Sau đây là cách họ thực hiện.
Phản hồi chậm, hiệu suất kém hơn
AirSHIFT là một ứng dụng web dành cho máy tính để bàn giúp chủ cửa hàng, như nhà hàng và quán cà phê, quản lý công việc theo ca của nhân viên. Được xây dựng bằng React, ứng dụng trang đơn này cung cấp các tính năng phong phú cho ứng dụng, bao gồm nhiều bảng lịch làm việc theo lưới được sắp xếp theo ngày, tuần, tháng, v.v.
Khi nhóm kỹ sư của Recruit Technologies thêm các tính năng mới vào ứng dụng AirSHIFT, họ bắt đầu nhận được nhiều ý kiến phản hồi hơn về hiệu suất chậm. Yosuke Furukawa, giám đốc kỹ thuật của AirSHIFT, cho biết:
Trong một nghiên cứu về người dùng, chúng tôi vô cùng sốc khi một trong những chủ cửa hàng nói rằng cô sẽ rời khỏi chỗ để pha cà phê sau khi nhấp vào một nút, chỉ để tiết kiệm thời gian chờ bàn ca làm việc tải xong.
Sau khi nghiên cứu, nhóm kỹ thuật nhận ra rằng nhiều người dùng của họ đang cố gắng tải các bảng chuyển đổi lớn trên các máy tính thông số thấp, chẳng hạn như máy tính xách tay Celeron M 1 GHz từ 10 năm trước.
Ứng dụng AirSHIFT đang chặn luồng chính bằng các tập lệnh đắt tiền, nhưng nhóm kỹ thuật không nhận ra các tập lệnh đắt tiền như thế nào vì các tập lệnh này đang phát triển và thử nghiệm trên các máy tính thông số kỹ thuật phong phú có kết nối Wi-Fi nhanh.
Sau khi phân tích hiệu suất của các công cụ này trong Công cụ của Chrome cho nhà phát triển có bật chế độ điều tiết CPU và mạng, rõ ràng là cần phải tối ưu hoá hiệu suất. AirSHIFT đã thành lập một đội đặc nhiệm để giải quyết vấn đề này. Dưới đây là 5 điều họ đã tập trung để cải thiện khả năng thích ứng của ứng dụng đối với hoạt động đầu vào của người dùng.
1. Ảo hoá bảng lớn
Việc hiển thị bảng ca làm việc đòi hỏi nhiều bước tốn kém: xây dựng DOM ảo và hiển thị trên màn hình tương ứng với số lượng nhân viên và khung giờ. Ví dụ: nếu một nhà hàng có 50 thành viên làm việc và muốn kiểm tra lịch làm việc hàng tháng của họ, thì đó sẽ là một bảng 50 (thành viên) nhân với 30 (ngày) sẽ dẫn đến 1.500 thành phần ô để hiển thị. Đây là một thao tác rất tốn kém, đặc biệt là đối với các thiết bị có thông số kỹ thuật thấp. Trên thực tế, mọi chuyện còn tệ hơn. Từ nghiên cứu họ biết được có những cửa hàng quản lý 200 nhân viên, yêu cầu khoảng 6.000 thành phần ô trong một bảng hàng tháng.
Để giảm chi phí của thao tác này, AirSHIFT đã ảo hoá bảng ca làm việc. Ứng dụng hiện chỉ gắn các thành phần trong khung nhìn và ngắt kết nối các thành phần ngoài màn hình.
Trong trường hợp này, AirSHIFT đã sử dụng tính năng ảo hoá phản ứng do có những yêu cầu liên quan đến việc bật các bảng lưới hai chiều phức tạp. Họ cũng đang tìm hiểu cách chuyển đổi quy trình triển khai để sử dụng cửa sổ phản ứng gọn nhẹ trong tương lai.
Kết quả
Chỉ ảo hoá bảng đã giảm thời gian viết tập lệnh xuống 6 giây (trên môi trường Macbook Pro bị điều tiết 4 lần + giảm tốc độ CPU gấp 4 lần). Đây là điểm cải thiện hiệu suất có tác động mạnh mẽ nhất trong dự án tái cấu trúc.
2. Kiểm tra bằng API Thời gian người dùng
Tiếp theo, nhóm AirSHIFT đã tái cấu trúc các tập lệnh chạy trên hoạt động đầu vào của người dùng. Biểu đồ ngọn lửa của Công cụ của Chrome cho nhà phát triển giúp bạn có thể phân tích những gì đang thực sự xảy ra trong luồng chính. Tuy nhiên, nhóm AirSHIFT thấy rằng việc phân tích hoạt động của ứng dụng dựa trên vòng đời của React trở nên dễ dàng hơn.
React 16 cung cấp dấu vết hiệu suất thông qua API Thời gian người dùng mà bạn có thể trực quan hoá từ phần Thời gian của Công cụ của Chrome cho nhà phát triển. AirSHIFT đã sử dụng mục Timings để tìm logic không cần thiết chạy trong các sự kiện trong vòng đời của React.
Kết quả
Nhóm AirSHIFT phát hiện ra rằng tính năng Điều chỉnh cây phản ứng không cần thiết đã được triển khai ngay trước mỗi lần di chuyển tuyến đường. Điều này có nghĩa là React cập nhật bảng thay đổi một cách không cần thiết trước các thao tác điều hướng. Việc cập nhật trạng thái Redux không cần thiết đã gây ra vấn đề này. Sửa lỗi này giúp tiết kiệm khoảng 750 mili giây thời gian viết tập lệnh. AirSHIFT cũng thực hiện các hoạt động tối ưu hoá vi mô khác, cuối cùng giúp giảm tổng thời gian viết tập lệnh xuống 1 giây.
3. Tải từng phần các thành phần và di chuyển logic tốn kém sang trình thực thi web
AirSHIFT có ứng dụng trò chuyện tích hợp sẵn. Nhiều chủ cửa hàng vừa trò chuyện với nhân viên vừa nhìn vào bảng ca làm việc để trao đổi với nhân viên, tức là có thể người dùng đang nhập tin nhắn trong khi bàn đang tải. Nếu luồng chính có các tập lệnh đang hiển thị bảng, thì hoạt động đầu vào của người dùng có thể bị giật.
Để cải thiện trải nghiệm này, AirSHIFT hiện sử dụng React.lazy và Suspense để hiển thị phần giữ chỗ cho mục lục trong khi tải từng phần các thành phần thực tế.
Nhóm AirSHIFT cũng đã di chuyển một số logic nghiệp vụ tốn kém trong các thành phần được tải từng phần sang trình chạy web. Việc này đã giải quyết vấn đề giật hoạt động đầu vào của người dùng bằng cách giải phóng luồng chính để có thể tập trung vào việc phản hồi hoạt động đầu vào của người dùng.
Thông thường, các nhà phát triển phải đối mặt với sự phức tạp khi sử dụng worker, nhưng lần này Comlink đã giúp họ xử lý phần việc khó khăn. Dưới đây là mã giả về cách AirSHIFT triển khai một trong những thao tác tốn kém nhất: tính tổng chi phí nhân công.
Trong App.js, hãy sử dụng React.lazy và Suspense để hiển thị nội dung dự phòng khi tải
/** App.js */
import React, { lazy, Suspense } from 'react'
// Lazily loading the Cost component with React.lazy
const Hello = lazy(() => import('./Cost'))
const Loading = () => (
<div>Some fallback content to show while loading</div>
)
// Showing the fallback content while loading the Cost component by Suspense
export default function App({ userInfo }) {
return (
<div>
<Suspense fallback={<Loading />}>
<Cost />
</Suspense>
</div>
)
}
Trong thành phần Cost (Chi phí), hãy sử dụng comlink để thực thi logic calc
/** Cost.js */
import React from 'react';
import { proxy } from 'comlink';
// import the workerlized calc function with comlink
const WorkerlizedCostCalc = proxy(new Worker('./WorkerlizedCostCalc.js'));
export default async function Cost({ userInfo }) {
// execute the calculation in the worker
const instance = await new WorkerlizedCostCalc();
const cost = await instance.calc(userInfo);
return <p>{cost}</p>;
}
Triển khai logic tính toán chạy trong worker và hiển thị logic đó bằng comlink
// WorkerlizedCostCalc.js
import { expose } from 'comlink'
import { someExpensiveCalculation } from './CostCalc.js'
// Expose the new workerlized calc function with comlink
expose({
calc(userInfo) {
// run existing (expensive) function in the worker
return someExpensiveCalculation(userInfo);
}
}, self);
Kết quả
Mặc dù có số lượng logic hạn chế mà chúng hoạt động dưới dạng thử nghiệm, nhưng AirSHIFT đã chuyển khoảng 100 mili giây JavaScript của họ từ luồng chính sang luồng thực thi (được mô phỏng với chế độ điều tiết CPU gấp 4 lần).
AirSHIFT hiện đang tìm hiểu xem họ có thể tải từng phần các thành phần khác và giảm tải thêm logic cho nhân viên web để giảm thiểu tình trạng giật hay không.
4. Đặt ngân sách hiệu suất
Sau khi triển khai tất cả các biện pháp tối ưu hoá này, điều quan trọng là phải đảm bảo ứng dụng vẫn hoạt động hiệu quả theo thời gian. AirSHIFT hiện sử dụng bundlesize để không vượt quá kích thước tệp JavaScript và CSS hiện tại. Ngoài việc đặt các mức ngân sách cơ bản này, họ còn tạo một trang tổng quan để hiển thị nhiều tỷ lệ phần trăm của thời gian tải bảng ca làm việc nhằm kiểm tra xem ứng dụng có hoạt động hiệu quả ngay cả trong các điều kiện không lý tưởng hay không.
- Thời gian hoàn thành tập lệnh cho mỗi sự kiện Redux hiện được đo lường
- Dữ liệu hiệu suất được thu thập trong Elasticsearch
- Hiệu suất ở phân vị thứ 10, 25, 50 và 75 của mỗi sự kiện được hiển thị bằng Kibana
AirSHIFT hiện đang theo dõi sự kiện tải bảng thay đổi để đảm bảo quá trình này hoàn thành trong 3 giây đối với người dùng ở phân vị thứ 75. Hiện tại, đây là ngân sách chưa thực thi, nhưng họ đang xem xét việc nhận thông báo tự động thông qua Elasticsearch khi họ vượt quá ngân sách.
Kết quả
Từ biểu đồ trên, bạn có thể thấy rằng AirSHIFT hiện chủ yếu đạt đến ngân sách 3 giây cho người dùng phân vị thứ 75 và cũng tải bảng thay đổi trong vòng một giây cho người dùng phân vị thứ 25. Bằng cách thu thập dữ liệu về hiệu suất của ứng dụng tròn từ nhiều điều kiện và thiết bị, AirSHIFT hiện có thể kiểm tra xem bản phát hành tính năng mới có thực sự ảnh hưởng đến hiệu suất của ứng dụng hay không.
5. Sự kiện hackathon hiệu suất
Mặc dù tất cả những nỗ lực tối ưu hoá hiệu suất này đều quan trọng và có tác động mạnh mẽ, nhưng không phải lúc nào nhóm kỹ sư và nhóm kinh doanh mới ưu tiên những hoạt động phát triển không vận hành chức năng. Một phần của thách thức là bạn không thể lên kế hoạch cho một số biện pháp tối ưu hoá hiệu suất này. Những chiến dịch này đòi hỏi phải thử nghiệm cũng như tư duy thử nghiệm và sửa sai.
AirSHIFT hiện đang tổ chức các sự kiện hackathon hiệu suất nội bộ trong 1 ngày để cho phép các kỹ sư chỉ tập trung vào các công việc liên quan đến hiệu suất. Trong các sự kiện hackathon này, họ loại bỏ mọi hạn chế và tôn trọng khả năng sáng tạo của các kỹ sư, nghĩa là bất kỳ cách triển khai nào góp phần tăng tốc độ đều đáng được cân nhắc. Để đẩy nhanh sự kiện này, AirSHIFT chia nhóm thành các nhóm nhỏ và mỗi đội sẽ cạnh tranh để xem ai có điểm cải thiện hiệu suất cao nhất từ Lighthouse. Các nhóm sẽ rất cạnh tranh! 🔥
Kết quả
Hướng tiếp cận của sự kiện hackathon đang có hiệu quả với họ.
- Bạn có thể dễ dàng phát hiện nút thắt cổ chai về hiệu suất bằng cách thực sự thử nhiều phương pháp trong sự kiện hackathon và đo lường từng phương pháp bằng Lighthouse.
- Sau sự kiện này, khá dễ để thuyết phục nhóm này nên ưu tiên tối ưu hóa cho quá trình phát hành phiên bản chính thức.
- Đây cũng là một phương pháp hiệu quả để ủng hộ tầm quan trọng của tốc độ. Mọi người tham gia đều có thể hiểu được mối tương quan giữa cách bạn lập trình và cách nó mang lại hiệu suất.
Một hiệu ứng phụ rất hay là nhiều nhóm kỹ thuật khác của Recruit đã quan tâm đến phương pháp thực tế này. Ngoài ra, nhóm AirSHIFT hiện đang hỗ trợ nhiều sự kiện hackathon tốc độ trong công ty.
Tóm tắt
Đây chắc chắn không phải là hành trình dễ dàng nhất để AirSHIFT thực hiện những việc tối ưu hoá này, nhưng điều này chắc chắn đã được đền đáp.
Sau khi tính năng tối ưu hoá hiệu suất được triển khai, một người dùng cho biết:
Cảm ơn bạn rất nhiều vì đã giúp bảng ca làm việc tải nhanh. Giờ đây, việc sắp xếp ca làm việc đã trở nên hiệu quả hơn rất nhiều.