Website WordPress chậm: đo đúng trước khi tối ưu
Đo tốc độ WordPress ở đâu, đo bằng số nào, ba bẫy làm số đo sai (PHP, plugin tối ưu, xoá cache) và thứ tự nên sửa, rút từ các dự án Halo đã làm.
Website WordPress chậm, phản xạ thường gặp là cài thêm plugin tối ưu, bấm "xoá toàn bộ cache", chạy PageSpeed rồi nhìn điểm. Cách đó dễ cho ra số đẹp mà sai, hoặc số xấu mà cũng sai. Halo từng viết trong một báo cáo khảo sát rằng khách phải chờ gần 7 giây. Đo lại kỹ, đồng hồ thật chỉ ghi 2,31 giây. Báo cáo đó mà đến tay khách, họ chỉ cần mở web thấy nhanh là mất lòng tin vào mọi phần còn lại. Bài này rút từ các dự án Halo đã làm, viết ẩn danh.
Tóm tắt nhanh
- Đo trên đúng máy chủ đang phục vụ khách, không đo trên bản dựng thử khác cấu hình.
- Muốn nói "khách chờ bao lâu" thì dùng dữ liệu người dùng thật của Google (CrUX), không dùng LCP mô phỏng, không dùng điểm PageSpeed.
- Trang chủ nhanh chưa nói lên gì. Hãy đo độ phủ cache trên nhiều trang ngẫu nhiên.
- Ba bẫy hay gặp: đọc phiên bản PHP ở dòng lệnh, plugin tối ưu tự làm vỡ trang, xoá cache sai cách trước khi đo.
Đo ở đâu: trên đúng máy chủ thật
Tốc độ phụ thuộc máy chủ: phần cứng, mạng, phần mềm máy chủ web, cache, phiên bản PHP. Vì vậy số đo trên bản dựng thử ở máy tính (ví dụ LocalWP) gần như vô nghĩa. Cache cấp máy chủ như LiteSpeed, nginx, Redis không mô phỏng được ở đó, và công cụ đo của Google phải gọi được vào một địa chỉ công khai.
Bản dựng thử trên máy chủ (staging) cũng phải giống bản thật ở những thứ ảnh hưởng tốc độ. Trong một dự án tối ưu tốc độ Halo từng làm, bản dựng thử ban đầu chạy nginx còn web thật chạy LiteSpeed. Vấn đề lớn nhất của web thật lại nằm ở cache của LiteSpeed: một cookie theo dõi nguồn truy cập (UTM) khiến cache từ chối lưu trang. Trên nginx, lỗi này không bao giờ hiện ra. Phải chuyển bản dựng thử sang máy chủ LiteSpeed mới thấy và sửa được.
Quy tắc rút gọn Halo dùng: chưa có gì để mất thì dựng thử trên máy; đã có dữ liệu thật hoặc kết quả phụ thuộc máy chủ thì làm trên máy chủ. Buộc phải khảo sát tạm trên máy thì ghi rõ mọi số đo tốc độ là tạm, đo lại trên máy chủ thật trước khi nghiệm thu.
Đo gì: mỗi câu hỏi một con số
LCP (Largest Contentful Paint) là lúc nội dung lớn nhất trên màn hình hiện ra. Ở chế độ điện thoại, Lighthouse (công cụ đứng sau PageSpeed Insights) không bóp mạng khi tải mà tải bình thường rồi tính ngược: nếu mạng 1,6 Mbps, độ trễ 150 ms, CPU chậm gấp 4 lần thì mất bao lâu. LCP báo cáo là kết quả phép tính, không phải đồng hồ bấm giờ.
Tệp kết quả JSON của Lighthouse lưu cả hai con số. Ở website khảo sát nêu đầu bài, LCP báo cáo là 7,04 giây, còn trường observedLargestContentfulPaint (đồng hồ thật) ghi 2,31 giây. Con số được dùng khi nói "khách chờ bao lâu" là CrUX (Chrome User Experience Report), dữ liệu từ người dùng thật, lấy mức p75, tức 75% lượt truy cập nhanh bằng hoặc hơn con số đó. Ở website này, LCP người dùng thật trên điện thoại là 3,18 giây tính cho toàn site.
| Cần trả lời | Dùng số nào | Tránh |
|---|---|---|
| Khách chờ bao lâu | CrUX p75 | LCP mô phỏng |
| Có đạt Core Web Vitals không | CrUX kèm xếp loại | Điểm Performance |
| Máy chủ có nhanh không | TTFB (thời gian tới byte đầu tiên) đo bằng curl | Điểm Lighthouse |
| Cải thiện được bao nhiêu | Đo trước và sau cùng một cách | So điểm khác ngày, khác cách đo |
Đừng nghiệm thu bằng điểm PageSpeed
Cũng website khảo sát đó, trong một ngày, điểm điện thoại đo được 43, 46, 61, 64, 65, 66; máy tính 67, 77, 84, 91. Nguyên nhân là lỗi giật bố cục (CLS) lúc có lúc không, mỗi lần xuất hiện kéo điểm tụt tới 24 điểm. Vì vậy Halo cam kết bằng giây, đo trên mạng thật, lấy trung vị nhiều trang. Khách nhất định muốn cam kết theo điểm thì khoá cách đo: trung vị 5 lần đo liên tiếp, ẩn danh, nêu rõ trang và thiết bị, chỉ tính điểm Performance.
Bộ đo tối thiểu và độ phủ cache
- TTFB trang chủ, đo 6 lần.
- Đo khi cache không phục vụ: thêm tham số ngẫu nhiên vào đường dẫn.
- Độ phủ cache: lấy 30 đường dẫn ngẫu nhiên từ sitemap, gọi mỗi đường dẫn đúng một lần, đếm tỉ lệ không trúng cache.
- Kiểm nén bằng yêu cầu GET. Dùng HEAD, Halo từng kết luận nhầm là web không nén trong khi Brotli đang bật.
Ở website khảo sát đó, trang chủ phản hồi trong 29 mili giây, nhưng 30 trang lấy ngẫu nhiên thì cả 30 không trúng cache, TTFB trung vị 0,82 giây, 23% vượt 3 giây, chậm nhất 9,93 giây. Trang chủ luôn "nóng", còn khoảng 2.000 trang bài viết và dự án, đúng nhóm khách vào từ Google, gần như luôn "nguội". Cách sửa lại rẻ: bật trình làm nóng cache.
Ba bẫy làm số đo sai
Bẫy 1: đọc phiên bản PHP ở dòng lệnh
Máy chủ thường cài nhiều bản PHP. Lệnh php -v chỉ cho biết bản PHP của dòng lệnh, không phải bản đang phục vụ khách. Trong dự án tối ưu nói trên, tài liệu ghi bản dựng thử chạy PHP 8.3 vì con số đọc từ dòng lệnh. Thực tế tầng web chạy PHP 7.4, do tên miền đó chưa được chọn phiên bản nên rơi vào mặc định. Cách kiểm đúng: đặt một tệp PHP nhỏ in ra phiên bản vào thư mục web, gọi bằng curl, đọc xong xoá ngay.
Trang chủ trả 200 cũng chưa chứng minh web sống. Halo từng gặp một web nâng PHP xong lỗi 500 toàn site, trang chủ vẫn trả 200 vì plugin cache phục vụ HTML tĩnh cũ.
Bẫy 2: plugin tối ưu tự làm vỡ trang
Plugin gộp và nén CSS, JS (minify) giúp trang nhẹ hơn nhưng có thể gây lỗi khó thấy. Halo gặp ở WP-Optimize bản 4.6.1: tác vụ dọn tệp cũ chạy hằng ngày xoá nhầm cả thư mục tệp gộp đang dùng, vì lớp bảo vệ so sánh một chuỗi với một số nên không bao giờ khớp. Cache trang vẫn giữ HTML trỏ tới tệp đã mất, nên trang vỡ bố cục mà mã HTTP vẫn 200. Lỗi lộ ra khoảng 30 ngày sau lần xoá cache gộp gần nhất, dễ đổ nhầm cho "ai vừa sửa gì". Bản 4.7.0 đã sửa.
Bài học: nghiệm thu không dừng ở mã 200 của trang. Kiểm từng tệp CSS, JS trang gọi tới, và mở trình duyệt thật để nhìn. Tuỳ chọn hoãn nạp JS cũng phải thử bằng thao tác thật, vì nút bấm có thể không phản hồi ngay trong khi chỉ số máy chủ vẫn đẹp.
Bẫy 3: xoá cache sai cách và đo bằng "bot"
Nhiều người bấm "xoá toàn bộ cache" trước mỗi lần đo. Ở dự án tối ưu nói trên, thao tác này của LiteSpeed Cache xoá luôn bộ nhớ đệm mã PHP (OPcache) và bộ CSS, JS đã gộp. Lượt tải kế tiếp mất khoảng 2,2 giây chỉ để biên dịch lại khoảng 3.000 tệp PHP, dẫn tới kết luận sai "nền TTFB là 2,2 giây". Nền thật là 0,57-0,80 giây. Cách đúng là thêm tham số ngẫu nhiên vào đường dẫn để né cache trang mà không phá lớp cache khác.
Cũng dự án đó, chế độ Guest Mode của LiteSpeed ưu đãi một danh sách nhận dạng trình duyệt, trong đó có HeadlessChrome, Lighthouse, GTmetrix, Pingdom. Công cụ tự động Playwright mặc định gửi nhận dạng HeadlessChrome. Cùng một trang, nhận dạng mặc định đo 765 mili giây, Chrome thật đo 4.707 mili giây. Mọi số đo trước khi phát hiện ra chuyện này đều là số của bot, kể cả kết luận "đã đạt chỉ tiêu".
Thứ tự ưu tiên khi sửa
Nguyên tắc của Halo: tối ưu bao nhiêu cũng được, nhưng không đánh đổi bằng thứ người dùng cảm nhận được. Nhanh hơn 0,2 giây không ai để ý, chức năng hỏng thì nhận ra ngay. Nghi ngờ thì hoàn tác. Thứ tự ưu tiên rút ra từ dự án tối ưu nói trên:
- Ghi mốc. Chụp ảnh giao diện, ghi số đo trước khi đụng vào bất cứ thứ gì.
- Cache trang có thật sự phục vụ không. Web thật trả "miss" ở 100% số lần đo, vì một plugin đặt cookie ở mọi lượt truy cập và ba khoá cấu hình chứa mẫu khớp gần như mọi đường dẫn, ép cả site sang cache riêng tư.
- Việc chạy ké lượt truy cập. Web có 45 tác vụ định kỳ của WordPress (WP-Cron) chạy ké vào lượt tải của khách. Chuyển sang lịch chạy của hệ thống, và nhớ: tắt WP-Cron mà không có lịch hệ thống thì mọi tác vụ định kỳ ngừng âm thầm.
- Plugin. Đo trước khi đổ lỗi: nạp 27 plugin tốn khoảng 300-420 mili giây, toàn bộ truy vấn chỉ 42-56 mili giây, nên cơ sở dữ liệu không phải nút thắt. Chỉ gỡ plugin đã quét xác minh là không dùng ở đâu.
- Giao diện nặng. JS gộp 1,28 MB, CSS 663 KB, ảnh trang chủ khoảng 2 MB. Làm sau cùng và thận trọng: hoãn nạp JS dễ làm vỡ giao diện, nén ảnh không được để mắt thường nhận ra.
Sau mỗi thay đổi, đo lại cả TTFB, số truy vấn và trải nghiệm trên trình duyệt. TTFB một mình không phát hiện được object cache đã chết hay JS đã hỏng. Trong dự án nói trên, sau bốn thay đổi ở tầng cache, một trang dịch vụ đo bằng Chrome thật lúc không trúng cache giảm từ 4.707 xuống 2.530 mili giây trên máy tính, từ 4.875 xuống 2.129 mili giây trên điện thoại, nội dung khớp 100%, form và menu vẫn chạy.
Đo đúng quyết định bạn sửa đúng chỗ hay sửa chỗ trông có vẻ chậm. Cần người trực web sau đó thì Halo Care theo dõi lỗi, tốc độ và sao lưu cho web WordPress.
Nguồn
- Đo tốc độ đúng: đừng biến số phòng thí nghiệm thành lời hứa, Halo Media, quy trình audit website (tài liệu nội bộ).
- Bẫy WP-Optimize: web mất CSS, JS vì tác vụ dọn minify xoá nhầm thư mục đang dùng, Halo Media, sự cố 01-02/10/2026 (tài liệu nội bộ).
- Làm việc ở đâu: máy, LocalWP hay VPS, Halo Media, 25/08/2026 (tài liệu nội bộ).
- Hồ sơ một dự án tối ưu tốc độ WordPress, Halo Media, 07-08/2026 (tài liệu nội bộ, ẩn danh khách hàng).