Categories Tối ưu CSS

Trì hoãn tải CSS không quan trọng

Các file CSS là loại tài nguyên chặn hiển thị: chúng phải được tải xuống (load) và xử lý (process) trước khi trình duyệt render trang. Trang web bao gồm lượng lớn các style không cần thiết có thể mất nhiều thời gian để render.

Trong bài hướng dẫn này, bạn sẽ học được cách làm thế nào để trì hoãn các CSS không quan trọng (non-critical CSS) với mục tiêu tối ưu hóa tuyến hiển thị quan trọng (critical rendering path), và cải thiện thời gian thấy nội dung đầu tiên xuất hiện (First Contentful Paint / FCP).


Tải CSS theo cách tối ưu

Ví dụ bên dưới bao gồm một accordion với ba khối văn bản ẩn, mỗi khối văn bản được style với class khác nhau: https://defer-css-unoptimized.glitch.me

Trang này yêu cầu một file CSS với tám class, nhưng không phải tất cả đều cần thiết để render nội dung “thấy bên ngoài”.

Mục tiêu của hướng dẫn này là tối ưu hóa trang trên, nhờ thế chỉ các style quan trọng là được tải theo cách đồng bộ (synchronously), trong khi phần còn lại (như những cái áp dụng cho khối văn bản ẩn bên dưới) được tải theo cách không chặn hiển thị (non-blocking).


Tiến hành kiểm tra

Chạy Lighthouse trên trang và đi đến phần Performance.

Báo có cho thấy chỉ số Fist Contentful Paint có giá trị là “1s”, và có cơ hội tăng tốc nhờ việc Loại bỏ các tài nguyên chặn hiển thị (Eliminate render-blocking resources), trỏ đến file style.css:

loại bỏ tài nguyên chặn hiển thị

Lưu ý: CSS mà chúng tôi sử dụng trong trang web demo này khá nhỏ. Nếu bạn yêu cầu các file CSS lớn hơn (điều không phải là hiếm trong các sản phẩm thực), và nếu Lighthouse phát hiện trang có ít nhất 2048 bytes (2 KB) quy tắc CSS không được sử dụng trong khi render nội dung thuộc màn hình đầu tiên (above the fold), bạn sẽ nhận thêm gợi ý được gọi là Loại bỏ CSS không sử dụng.

Để hình ảnh hóa cách CSS này chặn hiện thị bạn làm như sau:

  1. Mở trang trên Chrome.
  2. Nhấn Control + Shift + J hoặc Cmd + Option + J (Mac), để mở DevTools (công cụ cho nhà phát triển được tích hợp sẵn trong trình duyệt Chrome).
  3. Vào tab Preformance và click vào nút Reload.

Trong trace kết quả, bạn sẽ thấy FCP được đánh dấu tại vị trí ngay sau khi CSS được tải xong:

kiểm tra trên DevTools

Điều này có nghĩa là trình duyệt cần đợi tất cả CSS tải xong và xử lý chúng trước khi đưa ra được bất cứ pixel nào trên màn hình.


Tối ưu

Để tối ưu trang này, bạn cần biết class nào được xem là “quan trọng”. Bạn sẽ sử dụng Coverage Tool để làm điều này:

  1. Trong DevTools, mở Command Menu bằng cách nhấn tổ hợp phím Control + Shift + P hoặc Command + Shift + P (Mac);
  2. Gõ “Coverage” và chọn Show Coverage;
  3. Click nút Reload, để tải lại trang và bắt đầu ghi lại coverage.
coverage chưa tối ưu

Click đúp vào báo cáo, để xem các class được đánh dấu trong hai màu:

  • Màu xanh (quan trọng): Đây là những class mà trình duyệt cần để render nội dung cần nhìn ngay (như tiêu đề chính, tiêu đề phụ, và nút accordion).
  • Màu đỏ (không quan trọng): Đây là những style áp dụng cho nội dung không nhìn thấy ngay lập tức (như là các đoạn ẩn bên trong accordions).

Với thông tin này, bạn tối ưu hóa CSS của mình để trình duyệt tải và xử lý style quan trọng ngay lập tức ngay sau khi trang tải, trong khi trì hoãn các CSS không quan trọng về sau:

  • Trích xuất các class được đánh dấu màu xanh trong báo cáo thu được từ công cụ coverage, và đẩy các class này vào bên trong khối <style> ở đầu trang:
<style type="text/css">
.accordion-btn {background-color: #ADD8E6;color: #444;cursor: pointer;padding: 18px;width: 100%;border: none;text-align: left;outline: none;font-size: 15px;transition: 0.4s;}.container {padding: 0 18px;display: none;background-color: white;overflow: hidden;}h1 {word-spacing: 5px;color: blue;font-weight: bold;text-align: center;}
</style>
  • Sau đó tải các class còn lại theo phương thức không đồng bộ, bằng cách áp dụng mẫu bên dưới đây:
<link rel="preload" href="styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="styles.css"></noscript>

Đây không phải là cách tải CSS tiêu chuẩn. Đây là cách nó hoạt động:

  • link rel=”preload” as=”style” yêu cầu stylesheet tải không đồng bộ. Bạn có thể tìm hiểu về preload trong tài liệu hướng dẫn của nó ở đây: https://kiencang.net/preload-tai-nguyen-quan-trong/
  • Thuộc tính onload trong link cho phép CSS được xử lý khi nó tải xong.
  • “Vô hiệu hóa/Nulling” trình xử lý onload một khi nó được sử dụng giúp một số trình duyệt tránh gọi lại trình xử lý khi chuyển đổi thuộc tính rel.
  • Tham chiếu stylesheet bên trong phần tử noscript hoạt động như một biện pháp dự phòng trong trường hợp trình duyệt không thực thi JavaScript.

Trang kết quả sau chỉnh sửa giống y như phiên bản ban đầu của nó, thậm chí là khi phần lớn style đã được tải không đồng bộ. Dưới đây là cách các style được inline và yêu cầu không đồng bộ cho CSS trông như thế nào trong file HTML (tôi/người dịch chỉ copy nội dung trong tag head):

<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style type="text/css">
.accordion-btn {
width: 100%;
text-align: center;
font-size: 18px;
cursor: pointer;
color: #444;
background-color: #ADD8E6;
padding: 19px;
outline: none;
border: none;
border-radius: 2px;
}
.container {
display: none;
padding: 0 18px;
background-color: white;
overflow: hidden;
}
h1 {
word-spacing: 5px;
color: blue;
font-weight: bold;
text-align: center;
}
</style>
<link rel="preload" href="style.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript>
<link rel="stylesheet" href="style.css">
</noscript>
</head>

Kiểm tra lại

Sử dụng DevTools để chạy lại kiểm tra về Performance cho trang đã được tối ưu hóa.

Đánh dấu FCP xuất hiện trước khi trang yêu cầu CSS, điều này có nghĩa là trình duyệt không cần đợi CSS tải trước khi render trang:

kiểm tra lại hiệu suất cho trang đã được tối ưu hóa

Bước cuối cùng, chạy Lighthouse trên trang đã được tối ưu hóa.

Trong báo cáo, bạn sẽ thấy là FCP của trang đã giảm được 0,2s (cải thiện 20%):

báo cáo lighthouse cho trang đã được tối ưu hóa

Phần gợi ý Loại bỏ tài nguyên chặn hiển thị không còn xuất hiện dưới khu vực Cơ hội nữa, mà giờ nó nằm trong khu vực Các tiêu chuẩn đã đạt (Pass Audits):

không còn tài nguyên chặn hiển thị

Các bước tiếp theo và tham khảo

Trong hướng dẫn này, bạn sử dụng code vanilla (dạng code đơn giản, không có mã, tài nguyên của bên thứ ba nhúng vào) để triển khai tối ưu. Trong bối cảnh thực, sử dụng các hàm như loadCSS sẽ là thực hành tốt, nó có thể giản hóa hành động này và làm việc ổn thỏa trên nhiều trình duyệt. Bổ sung cho bài viết này bạn có thể tham khảo bài hướng dẫn trích xuất critical CSS, nó có đề cập đến một số công cụ phổ biến nhất để trích xuất CSS quan trọng và bao gồm một codelab để bạn thấy cách thức chúng hoạt động trong thực tế.

(Dịch từ bài viết Defer non-critical CSS, tác giả: Demian Renzulli, trang: web[.]dev)

Back to Top