- ngày ghi
- phút đọc
- 7
- nguồn dẫn
- 8
Web chậm trên điện thoại: thủ phạm là không có màn hình chờ
Truy vấn dữ liệu 67 tới 266 mili giây, còn màn hình chờ thì 0 trên 23 trang. Dung lượng tải về 102 kB cũng không phải thủ phạm. Cảm giác đơ đến từ khoảng lặng sau cú bấm, sửa bằng 12 khung chờ.
- hiệu năng
- erp
- vận hành
Người dùng trong công ty phản ánh: "web chậm, đặc biệt trên điện thoại". Tôi nghi kho dữ liệu trước, rồi nghi dung lượng JavaScript. Tôi đo trước, sửa sau. Số đo chỉ sang chỗ thứ ba.
Đo trước, đoán sau
Tôi đo ba thứ.
Truy vấn kho dữ liệu. Đo từ máy tại Việt Nam: 67 tới 266 mili giây mỗi truy vấn. Các danh sách đều gọi song song, sạch kiểu gọi lặp từng dòng. Mọi truy vấn danh sách đều đặt giới hạn số dòng ở mức 100, 500, 1000 hoặc 2000.
Dung lượng JavaScript. Số lấy từ lần dựng bản mới ngày 29/07/2026:
| Trang | Dung lượng tải lần đầu |
|---|---|
| Dùng chung cho mọi trang | 102 kB |
| Trang chủ, nội dung, công việc, việc của tôi, tải việc | 106 kB |
| Doanh thu | 130 kB |
| Nhân sự, dự án | 146 kB |
| Chi phí | 167 kB |
| Bảng công việc (nặng nhất trong menu) | 190 kB |
| Người dùng | 200 kB |
| Cơ hội bán hàng (nặng nhất toàn hệ, đang ẩn khỏi menu) | 222 kB |
100-190 kB là mức bình thường của một ứng dụng React. Chỗ tối ưu nằm nơi khác.
Số màn hình chờ. Tìm khắp mã nguồn: 0 file khai báo màn hình chờ. Trong khi đó khu ứng dụng có 23 trang khai báo dựng lại mỗi lần mở: 23 trang dựng động, 0 màn hình chờ.
Điểm thứ ba mới là câu trả lời.
Cảm giác đơ đến từ khoảng lặng
Next.js chỉ hiện phản hồi tức thì khi trang có khai báo màn hình chờ. Thiếu khai báo đó, bấm chuyển trang xong web giữ nguyên trang cũ: màn hình đứng im cho tới khi máy chủ dựng xong. Trên 4G độ trễ cao, khoảng lặng đó dài 0,5-2 giây. Người dùng nghĩ máy treo nên bấm lại. Càng chậm thêm.
Bên dưới còn một chi phí cố định. Mỗi lần chuyển trang tốn hai vòng gọi tới dịch vụ xác thực: một ở lớp trung gian để làm mới phiên, một ở chính trang. Vòng gọi ở trang đã có bộ nhớ đệm, nhưng vẫn tách biệt với lớp trung gian.
Tệ hơn, danh sách loại trừ của lớp trung gian trước đó chỉ có ảnh. Ba file font và file khai báo ứng dụng vẫn chạy qua lớp đó, mỗi file kéo thêm một vòng gọi xác thực khi mở trang lần đầu.
Độ trễ của mỗi vòng gọi xác thực từ máy người dùng thì chưa đo. Tôi ghi "chưa đo" kèm cách đo, và để trống ô số.
Sửa: 12 khung xương bám bố cục thật
Nguyên tắc của đợt này: chỉ thêm file mới, giữ nguyên mọi trang đang chạy. Một file chứa các khối khung dùng chung, cộng 12 màn hình chờ: một khung mặc định cho cả khu ứng dụng và 11 khung riêng cho nội dung, chi tiết bài nội dung, bảng công việc, công việc, việc của tôi, dự án, cổng duyệt, điều hành, chi phí, doanh thu, nhân sự.
Cách dựng khung:
- Đọc từng trang rồi dựng lại đúng số khối, số cột bảng, chiều cao hàng, bề rộng cột bảng công việc 280 px, lưới chỉ số giữ chiều cao tối thiểu 118 px. Dữ liệu về thì bố cục đứng yên.
- Chỉ dùng màu trung tính lấy từ bộ màu chung, tự đúng ở cả nền sáng lẫn nền tối.
- Dựng hoàn toàn ở máy chủ, không giữ trạng thái. Bảng dung lượng ở trên được đo lại sau khi thêm khung chờ, vẫn đúng dải 102 tới 222 kB, y nguyên số byte.
- Mỗi khung khai báo đúng vai trò cho trình đọc màn hình, kèm một nhãn ẩn nói rằng dữ liệu đang tải. Giao diện đã tắt chuyển động khi người dùng bật chế độ giảm chuyển động.
- Ưu tiên đúng 5 thẻ trên thanh điều hướng điện thoại: trang chủ, công việc, dự án, nội dung, cổng duyệt.
Một đánh đổi tôi chấp nhận: trang chủ dùng chung khung mặc định, cố tình trung tính, bỏ dải chào mừng nhiều màu. Muốn khớp hoàn toàn phải tách trang chủ ra một nhóm tuyến riêng trên hệ đang chạy, đổi lấy khoảng nửa giây thẩm mỹ. Tôi để sau.
Sửa thứ hai là siết danh sách file đi qua lớp trung gian. Thêm các đuôi ảnh, biểu tượng, font, khai báo ứng dụng, văn bản thuần và sơ đồ nguồn vào danh sách loại trừ. Hết chuyện ba file font và file khai báo kéo theo một vòng gọi xác thực mỗi cái.
Vì sao an toàn, tôi kiểm từng ý. Cổng đăng nhập của khu ứng dụng nằm ở lớp bố cục chung. Lớp trung gian chỉ làm mới phiên và chặn thêm 4 nhánh đường dẫn, cả 4 đều nằm trong khu ứng dụng nên lớp bố cục đã gác sẵn. Chạy luật mới trên danh sách đường dẫn thật: mọi đường dẫn ứng dụng vẫn qua lớp trung gian như cũ.
Tôi giữ nguyên phần dịch vụ dữ liệu, dù cả 9 đường dịch vụ đều tự kiểm phiên bên trong. Bỏ lớp trung gian ở đó có rủi ro đăng xuất bất chợt khi hai yêu cầu cùng làm mới phiên một lúc. Để lại đợt sau.
Vì sao tôi giữ chế độ dựng lại mỗi lần mở
Đề xuất dễ nghe nhất là bỏ chế độ dựng lại mỗi lần mở, hoặc bật bộ nhớ đệm. Trang sẽ nhanh lên. Nhưng với trang có dữ liệu riêng theo từng người, và ở đây là gần như mọi trang trong hệ, hệ thống sẽ dùng chung một bản đã lưu đệm cho nhiều người. Người này thấy dữ liệu của người kia. Với một ERP đang phục vụ người dùng, đó là sự cố dữ liệu. Đợt này tôi giữ nguyên cách lưu đệm của mọi trang.
Tương tự với ý gộp hai vòng gọi xác thực bằng cách để lớp trung gian ghi kết quả vào phần đầu của yêu cầu rồi trang đọc lại. Tin vào phần đầu đó mà bỏ bước xác thực lại là mẫu từng gây lỗ hổng bỏ qua đăng nhập. Chỉ cân nhắc khi đo được độ trễ xác thực trên 300 mili giây, và có người soát riêng phần bảo mật.
Đo lại thế nào để biết có nhanh thật
Phép đo phải chạy trên mạng thật, vì mở thẳng trên máy đang lập trình thì không có độ trễ mạng. Cách đo: mở công cụ mạng của Chrome, giả lập mạng 4G, bấm lần lượt Công việc, Dự án, Nội dung, Duyệt rồi nhìn thời gian máy chủ trả về byte đầu tiên.
Thời gian đó gần như giữ nguyên, vì khung chờ đổi cảm giác chứ chưa đổi tốc độ máy chủ. Thời gian từ lúc bấm đến lúc màn hình đổi mới là phần giảm: trước bằng đúng thời gian máy chủ trả lời, sau còn một khung hình, khoảng 16 mili giây.
Kiểm sau sửa: bộ kiểm kiểu dữ liệu sạch, 0 lỗi. Bản dựng thành công, dung lượng tải lần đầu giữ nguyên. Tôi xem trên bản chạy thật ở khung nhìn 375×812, làm chậm phần lấy dữ liệu thêm 5 giây để giữ màn hình chờ. Khung hiện đúng bố cục trang đích. Thanh tiêu đề và thanh điều hướng đổi ngay khi bấm. Bố cục gọn trong khung: bề rộng cuộn bằng đúng bề rộng màn hình, 375. Bảng nội dung rộng 980 px cuộn bên trong khung của nó.
Còn để lại hai việc rẻ tiền: logo 600×299 px nặng 146 kB nhưng hiển thị ở 30 px chiều cao, và 3 file font tổng 841 kB chưa chuyển sang định dạng nén. Đợt sau.
Điều tôi rút ra
- "Chậm" là cảm nhận, phải đo ra số trước khi chọn chỗ sửa. Tôi suýt tối ưu kho dữ liệu trong khi kho dữ liệu chỉ mất 67 tới 266 mili giây.
- Chỗ sửa an toàn nhất thường là chỗ chỉ thêm file mới. 12 màn hình chờ giữ nguyên hành vi mọi trang và giữ nguyên số byte.
- Tốc độ đứng sau việc giữ dữ liệu của mỗi người ở đúng chỗ. Bộ nhớ đệm và chế độ dựng lại mỗi lần mở là quyết định của chủ hệ thống.
- Việc chưa đo thì ghi "chưa đo", kèm cách đo. Ô số để trống cho tới khi có phép đo.
Nếu công ty bạn cũng đang nghe câu "web chậm" mà chưa biết chậm ở đâu, kể tôi nghe bối cảnh.