Dùng Profile để kiểm tra hiệu suất của React App
Tags: react, tutorial
Published: 2022-05-24 01:37:02

Bài viết được dịch từ:
https://kentcdodds.com/blog/profile-a-react-app-for-performance

Thực hành dựa trên [source code](https://github.com/kentcdodds/bookshelf)

### Cài đặt Extension

Cần cài **React DevTools extension**.

### Khởi động app

Ứng dụng bookshelf sử dụng  `react-scripts` (nhờ `create-react-app`), vì vậy sau khi bạn đã cài đặt dự án ở máy mình, hãy chạy `npm run start` để chạy server. Thao tác này sẽ hiển thị ứng dụng trong trình duyệt của bạn tại `http://localhost: 3000`:


![Image anh 1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4u66q0xs7xe53dmfvqj3.PNG)

### Profiler

F12 trên browser chọn tab **Profiler**. Bây giờ bạn có thể ấn vào vòng tròn nhỏ màu xanh lam để **"Start profiling"** ứng dụng.

![Image anh 2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/px5bwkt9s29385ratn7y.PNG)

Từ đây, hãy tiếp tục và tương tác với ứng dụng một chút. Tôi sẽ đăng ký một tài khoản mới. Sau đó ấn vào vòng tròn nhỏ màu đỏ để **"Stop profiling."**

![Image anh 3](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/76ualpfzdzq1f1k0c6gf.PNG)

### Khám phá dữ liệu hồ sơ

Từ đây, bạn có một số tùy chọn để khám phá dữ liệu mà DevTools đã thu thập khi bạn tương tác với ứng dụng. Chế độ xem mặc định là "Flamegraph chart" và cũng có "Ranked chart". Đây là "Flamegraph chart" trông như thế nào (nếu bạn muốn xem "Ranked chart", bạn sẽ phải tự mình làm điều này 😜):

![Image anh 4](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/669hx36iii9a4fi2i0vf.PNG)

Chúng ta có thể đi sâu vào phân tích nội dung này trong một bài đăng khác.

### Cạm bẫy: đo lường ở chế độ phát triển

Tôi muốn chỉ ra một cạm bẫy nghiêm trọng mà bạn cần tránh khi thực hiện các phép đo hiệu suất như lập hồ sơ (Profiling). Hiện tại, chúng ta đang đo lường hiệu quả hoạt động của ứng dụng trong chế độ phát triển. Nếu bạn đã sử dụng React được một thời gian, bạn  biết rõ rằng nó có rất nhiều cảnh báo ở môi trường phát triển để giúp bạn tránh khỏi các vấn đề do code sai lý thuyết. Đây là một trong những điều tôi yêu thích nhất ở React, nhưng điều đó đi kèm với chi phí hiệu suất (thường là đáng kể).

Do đó, các phép đo hiệu suất của bạn bị nhiễm bẩn bởi môi trường phát triển của React.

Vì vậy, nếu bạn muốn có được phép đo chính xác về hiệu suất của ứng dụng trên môi trường production, bạn nên đảm bảo thực hiện các phép đo trên môi trường production.

### Build và đo trên môi trường production

Vì vậy, hãy chạy `npm run build`. Tiếp theo, chạy `npx serve -s build` để chạy trên server. Vào port 5000 và chạy profiler. Nhưng không?!

![Image 5](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y01pa5uxil5ovhjca8yy.PNG)

> Profiling not supported.
Profiling support requires either a development or production-profiling build of React v16.5+.
Learn more at fb.me/react-profiling.

Hóa ra, React có code dành riêng cho việc lập hồ sơ và vì lợi ích của việc làm cho ứng dụng của bạn nhanh nhất có thể, họ đã xóa code đó khỏi môi trường production.

>LƯU Ý: Nếu bạn đang sử dụng `create-react-app` với `react-scripts @> = 3.2.0` thì bạn có thể chỉ cần chạy `npx react-scripts build --profile` và nó sẽ thực hiện tất cả những việc này cho bạn (nhờ Jacob) và bạn có thể bỏ qua cạm bẫy tiếp theo. Nếu không, vui lòng đọc tiếp.

### Cập nhật cấu hình webpack để tạo hồ sơ trên môi trường production

Như lưu ý trên, ở môi trường production loại bỏ hầu hết các code hữu ích ở môi trường phát triển, nhưng vẫn giữ nguyên đoạn code lập hồ sơ. Nó vẫn chậm hơn một chút, nhưng nó cho chúng ta ý tưởng  về cách các component của chúng ta đang hoạt động trong môi trường production.

Có một số cách để giải quyết vấn đề này, nhưng đơn giản nhất là **cập nhật cấu hình webpack thành alias** bất kỳ import nào của các mô-đun nhất định vào phiên bản lập hồ sơ của mô-đun đó. Có hai mô-đun như vậy:

- `react-dom` -> `react-dom/profiling`
- `scheduler/tracing -> `scheduler/tracing-profiling`

Cả hai đều là các package React và cần đoạn code đặc biệt để việc lập hồ sơ hoạt động.

Cách bạn cập nhật cấu hình webpack sẽ khác nhau dựa trên framework bạn đang sử dụng (create-react-app, next.js, gatsby.js hoặc của riêng bạn với webpack tự xây). Trong trường hợp này, chúng tôi đang sử dụng **create-react-app** và không có cách nào được hỗ trợ chính thức để mở rộng hoặc sửa đổi cấu hình **webpack**.
Vì đang test ở local nên chúng ta có thể sửa trong **node_modules**

Vì vậy, nếu bạn đang sử dụng **react-scripts@3.1.1** (hoặc ở đâu đó xung quanh đó), thì bạn có thể mở cấu hình webpack tại đây: **./node_modules/react-scripts/config/webpack.config.js**

Sau đó xác định vị trí code trông giống như thế này và thêm các dòng ghi chú:

![Image 1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cq3xzebsaymeo4dwn4cy.PNG)

### Lập hồ sơ cho bản build ở môi trường production

Bây giờ hãy chạy `npm run build`, sau đó `npx serve -s build` và hãy lập hồ sơ ứng dụng một lần nữa! Tôi sẽ làm theo các bước đăng ký giống như lần trước.

![Image 6](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yzotw0xajbkxii52tr5p.PNG)

Bạn sẽ nhận thấy rằng đây là lần tương tác giống như lần trước (nó hiển thị trang sau khi đăng ký) và chúng tôi đã tăng từ 13,7 mili giây xuống 6,5 mili giây. Cải tiến tốt đẹp!

Nhưng thành phần **Ẩn danh** này có gì ở khắp nơi vậy? Và chúng tôi có một thành phần được gọi là **ee** khác được gọi là **Z**? Huh? Những gì đang xảy ra ở đây? Chà, bởi vì chúng tôi đang xây dựng ứng dụng của mình cho **production**, chúng ta đang giảm thiểu mã của mình để tải / phân tích cú pháp nhanh hơn, đây là một điều tốt cho người dùng cuối, nhưng lại là một điều tồi tệ đối với việc đo lường hiệu suất vì điều đó gây khó khăn cho chúng ta để biết thành phần nào trong số những thành phần này là thủ phạm gây ra các vấn đề về hiệu suất.

### Tắt chức năng name mangling

React biết cách gọi các **components** của bạn dựa trên thuộc tính `name`của **component**:

![Image 7](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5012qit12wy5yypmszfs.PNG)

Tuy nhiên, khi chúng tôi tạo mã bằng "uglifier" hoặc "minifier", công cụ sẽ thay đổi những tên đó theo cách làm cho code hoạt động giống như trước đây, nhưng giảm kích thước tệp để cải thiện hiệu suất :

![Image 8](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9j8htfgjq08oy9batvl4.PNG)

Đây là lý do tại sao chúng ta thấy những cái tên kì quặc này trong các phép đo hiệu suất. Vì vậy, cần phải tắt tính năng mangling này.

**create-react-app** sử dụng một công cụ có tên là Terser thông qua **terser-webpack-plugin** để thực hiện việc thu nhỏ, vì vậy chúng ta chỉ cần cập nhật cấu hình để giữ nguyên hàm và tên class.

Vì vậy, trong cùng một tệp cấu hình webpack đó, hãy cuộn xuống nơi plugin được cấu hình và sửa đổi nó như sau:

![Image 9](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fjchemv16601a72lr0k1.PNG)

Với **keep_classnames** và **keep_fnames** được định cấu hình thành true, bây giờ hãy thử build app và chạy một phiên cấu hình một lần nữa!

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ine3h8fd8p9qh6o3vbk9.PNG)

### Cạm bẫy: Lập hồ sơ bằng máy tính nhanh

Tôi đảm bảo với bạn rằng hầu hết các bạn đang đọc bài viết này hiện đang phát triển ứng dụng của mình bằng một thiết bị mạnh mẽ hơn hầu hết những người đang sử dụng ứng dụng. Không có gì thay thế cho việc thử ứng dụng của bạn trên các thiết bị mà người dùng sẽ sử dụng. Điều đó nói rằng, bạn có thể hiểu rõ hơn nhiều về hiệu suất thực tế của ứng dụng nếu bạn điều chỉnh CPU để mô phỏng trải nghiệm của một số người dùng ứng dụng của bạn.

Vì vậy, chúng ta hãy làm điều đó. Ấn vào tab "Performance" của Chrome DevTools, sau đó vào biểu tượng bánh răng để hiển thị cài đặt, sau đó trên tùy chọn CPU, chọn "6x slowdown.".

![Image 11](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s3e45w8v4g92ugr4e4lh.PNG)

Bây giờ hãy làm lại toàn bộ và kiểm tra sự khác biệt:

![Image 12](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fsvyqpdebtsmo0ue0hu1.PNG)

Phù! 31,8 mili giây! Đó là khá chậm! Tìm hiểu thêm về tác động của thời gian đó đối với trải nghiệm của người dùng trong bài đăng blog này có tiêu đề [Rendering Performance.](https://web.dev/rendering-performance/) Đây có thể là một cái gì đó đáng xem xét! Nhưng chúng tôi sẽ lưu nó cho một bài đăng blog khác 😉