Khắc phục tình trạng bố cục không ổn định

Hướng dẫn cách sử dụng WebPageTest để xác định và khắc phục các vấn đề về bố cục không ổn định.

Trong một bài đăng trước đó, tôi đã viết về cách đo lường Điểm số tổng hợp về mức thay đổi bố cục (CLS) trong WebPageTest. CLS là một chỉ số tổng hợp của tất cả các mức thay đổi bố cục, vì vậy, trong bài đăng này, tôi nghĩ sẽ rất thú vị nếu tìm hiểu sâu hơn và kiểm tra từng mức thay đổi bố cục riêng lẻ trên một trang để cố gắng tìm hiểu nguyên nhân có thể gây ra sự không ổn định và thực sự cố gắng khắc phục(các) vấn đề.

Đo lường mức thay đổi bố cục

Bằng cách sử dụng Layout Instability API, chúng ta có thể nhận được danh sách tất cả các sự kiện thay đổi bố cục trên một trang:

new Promise(resolve => {
  new PerformanceObserver(list => {
    resolve(list.getEntries().filter(entry => !entry.hadRecentInput));
  }).observe({type: "layout-shift", buffered: true});
}).then(console.log);

Thao tác này tạo ra một mảng các lượt thay đổi bố cục không có sự kiện đầu vào trước đó:

[
  {
    "name": "",
    "entryType": "layout-shift",
    "startTime": 210.78500000294298,
    "duration": 0,
    "value": 0.0001045969445437389,
    "hadRecentInput": false,
    "lastInputTime": 0
  }
]

Trong ví dụ này, chỉ có một thay đổi rất nhỏ là 0,01% ở 210 mili giây.

Việc biết được thời gian và mức độ thay đổi là rất hữu ích để giúp bạn xác định nguyên nhân có thể gây ra sự thay đổi đó. Hãy quay lại WebPageTest để có môi trường phòng thí nghiệm nhằm thực hiện thêm các kiểm thử.

Đo lường mức thay đổi bố cục trong WebPageTest

Tương tự như việc đo lường CLS trong WebPageTest, việc đo lường từng mức thay đổi bố cục sẽ yêu cầu một chỉ số tuỳ chỉnh. Rất may là quá trình này đã trở nên dễ dàng hơn kể từ khi Chrome 77 ra mắt phiên bản ổn định. Layout Instability API được bật theo mặc định, vì vậy, bạn có thể thực thi đoạn mã JS đó trên mọi trang web trong Chrome 77 và nhận được kết quả ngay lập tức. Trong WebPageTest, bạn có thể sử dụng trình duyệt Chrome mặc định mà không cần lo lắng về các cờ dòng lệnh hoặc việc sử dụng Canary.

Vì vậy, hãy sửa đổi tập lệnh đó để tạo một chỉ số tuỳ chỉnh cho WebPageTest:

[LayoutShifts]
return new Promise(resolve => {
  new PerformanceObserver(list => {
    resolve(JSON.stringify(list.getEntries().filter(entry => !entry.hadRecentInput)));
  }).observe({type: "layout-shift", buffered: true});
});

Lệnh hứa trong tập lệnh này sẽ phân giải thành một biểu thị JSON của mảng thay vì chính mảng đó. Điều này là do chỉ số tuỳ chỉnh chỉ có thể tạo ra các kiểu dữ liệu nguyên thuỷ như chuỗi hoặc số.

Trang web mà tôi sẽ dùng để kiểm tra là ismyhostfastyet.com, một trang web tôi tạo ra để so sánh hiệu suất tải thực tế của các máy chủ lưu trữ web.

Xác định nguyên nhân gây ra sự bất ổn về bố cục

Trong kết quả, chúng ta có thể thấy chỉ số tuỳ chỉnh LayoutShifts có giá trị sau:

[
  {
    "name": "",
    "entryType": "layout-shift",
    "startTime": 3087.2349999990547,
    "duration": 0,
    "value": 0.3422101449275362,
    "hadRecentInput": false,
    "lastInputTime": 0
  }
]

Tóm lại, có một lần thay đổi bố cục duy nhất là 34,2% xảy ra ở 3087 mili giây. Để xác định nguyên nhân gây ra vấn đề, hãy sử dụng chế độ xem cuộn phim của WebPageTest.

Hai ô trong dải phim, cho thấy ảnh chụp màn hình trước và sau khi xảy ra sự thay đổi bố cục.
Hai ô trong dải phim, cho thấy ảnh chụp màn hình trước và sau khi thay đổi bố cục.

Khi di chuyển đến mốc khoảng 3 giây trong dải phim, chúng ta sẽ thấy chính xác nguyên nhân gây ra hiện tượng thay đổi bố cục 34%: đó là bảng có nhiều màu sắc. Trang web tìm nạp không đồng bộ một tệp JSON, sau đó hiển thị tệp đó thành một bảng. Ban đầu, bảng này trống, nên việc chờ điền dữ liệu khi kết quả được tải sẽ gây ra hiện tượng dịch chuyển.

Phần đầu phông chữ trên web xuất hiện một cách bất ngờ.
Tiêu đề phông chữ trên web xuất hiện một cách bất ngờ.

Nhưng đó chưa phải là tất cả. Khi trang hoàn tất về mặt hình ảnh ở khoảng 4,3 giây, chúng ta có thể thấy <h1> của trang "Is my host fast yet?" (Máy chủ lưu trữ của tôi đã nhanh chưa?) xuất hiện một cách bất ngờ. Điều này xảy ra vì trang web sử dụng một phông chữ trên web và chưa thực hiện bất kỳ bước nào để tối ưu hoá quá trình hiển thị. Bố cục thực sự không bị thay đổi khi điều này xảy ra, nhưng việc phải đợi quá lâu để đọc tiêu đề vẫn là một trải nghiệm không tốt cho người dùng.

Khắc phục tình trạng bố cục không ổn định

Giờ đây, khi chúng ta biết rằng bảng được tạo không đồng bộ đang khiến 1/3 khung hiển thị bị thay đổi, thì đã đến lúc khắc phục vấn đề này. Chúng ta không biết nội dung của bảng cho đến khi kết quả JSON thực sự được tải, nhưng chúng ta vẫn có thể điền vào bảng một số loại dữ liệu giữ chỗ để bản thân bố cục tương đối ổn định khi DOM được kết xuất.

Dưới đây là mã để tạo dữ liệu giữ chỗ:

function getRandomFiller(maxLength) {
  var filler = '█';
  var len = Math.ceil(Math.random() * maxLength);
  return new Array(len).fill(filler).join('');
}

function getRandomDistribution() {
  var fast = Math.random();
  var avg = (1 - fast) * Math.random();
  var slow = 1 - (fast + avg);
  return [fast, avg, slow];
}

// Temporary placeholder data.
window.data = [];
for (var i = 0; i < 36; i++) {
  var [fast, avg, slow] = getRandomDistribution();
  window.data.push({
    platform: getRandomFiller(10),
    client: getRandomFiller(5),
    n: getRandomFiller(1),
    fast,
    avg,
    slow
  });
}
updateResultsTable(sortResults(window.data, 'fast'));

Dữ liệu của phần giữ chỗ được tạo ngẫu nhiên trước khi được sắp xếp. Nội dung này bao gồm ký tự "█" được lặp lại một số lần ngẫu nhiên để tạo các phần giữ chỗ trực quan cho văn bản và một bản phân phối ngẫu nhiên của 3 giá trị chính. Tôi cũng thêm một số kiểu để giảm độ bão hoà của tất cả màu trong bảng nhằm cho thấy rõ rằng dữ liệu chưa được tải đầy đủ.

Hình thức của các phần giữ chỗ bạn sử dụng không ảnh hưởng đến độ ổn định của bố cục. Mục đích của các phần giữ chỗ là để đảm bảo với người dùng rằng nội dung sắp xuất hiện và trang không bị lỗi.

Đây là hình thức của các trình giữ chỗ trong khi dữ liệu JSON đang tải:

Bảng dữ liệu được hiển thị bằng dữ liệu giữ chỗ.
Bảng dữ liệu được kết xuất bằng dữ liệu giữ chỗ.

Việc giải quyết vấn đề về phông chữ trên web sẽ đơn giản hơn nhiều. Vì trang web đang sử dụng Google Fonts, nên chúng ta chỉ cần truyền thuộc tính display=swap trong yêu cầu CSS. Chỉ có vậy thôi. Fonts API sẽ thêm kiểu font-display: swap vào khai báo phông chữ, cho phép trình duyệt hiển thị ngay văn bản bằng phông chữ dự phòng. Dưới đây là mã đánh dấu tương ứng có chứa bản sửa lỗi:

<link href="https://fonts.googleapis.com/css?family=Chivo:900&display=swap" rel="stylesheet">

Xác minh các hoạt động tối ưu hoá

Sau khi chạy lại trang thông qua WebPageTest, chúng ta có thể tạo một so sánh trước và sau để hình dung sự khác biệt và đo lường mức độ bất ổn mới của bố cục:

Dải băng hình của WebPageTest cho thấy cả hai trang web đang tải song song có và không có chế độ tối ưu hoá bố cục.
Dải băng hình của WebPageTest cho thấy cả hai trang web đang tải song song có và không có chế độ tối ưu hoá bố cục.
[
  {
    "name": "",
    "entryType": "layout-shift",
    "startTime": 3070.9349999997357,
    "duration": 0,
    "value": 0.000050272187989256116,
    "hadRecentInput": false,
    "lastInputTime": 0
  }
]

Theo chỉ số tuỳ chỉnh, vẫn có một sự thay đổi bố cục xảy ra ở 3071 mili giây (gần bằng thời gian trước đó) nhưng mức độ nghiêm trọng của sự thay đổi này nhỏ hơn nhiều: 0,005%. Tôi có thể chấp nhận điều này.

Thanh xem trước cũng cho thấy rõ rằng phông chữ <h1> đang chuyển ngay sang phông chữ hệ thống, giúp người dùng đọc được nội dung sớm hơn.

Kết luận

Các trang web phức tạp có thể sẽ gặp phải nhiều thay đổi bố cục hơn so với ví dụ này, nhưng quy trình khắc phục vẫn giống nhau: thêm các chỉ số về sự bất ổn của bố cục vào WebPageTest, tham chiếu chéo kết quả với dải hình ảnh tải trực quan để xác định nguyên nhân và triển khai giải pháp bằng cách sử dụng phần giữ chỗ để dành riêng không gian màn hình.

(Một điều nữa) Đo lường sự bất ổn về bố cục mà người dùng thực gặp phải

Thật tuyệt khi có thể chạy WebPageTest trên một trang trước và sau khi tối ưu hoá, đồng thời nhận thấy một chỉ số được cải thiện. Tuy nhiên, điều thực sự quan trọng là trải nghiệm người dùng thực sự được cải thiện. Đó chẳng phải là lý do chúng ta đang cố gắng cải thiện trang web ngay từ đầu sao?

Vì vậy, điều tuyệt vời là nếu chúng ta bắt đầu đo lường trải nghiệm về sự bất ổn của bố cục của người dùng thực cùng với các chỉ số hiệu suất truyền thống của trang web. Đây là một phần quan trọng của vòng lặp phản hồi tối ưu hoá vì việc có dữ liệu từ thực tế cho chúng ta biết vấn đề nằm ở đâu và liệu các bản sửa lỗi của chúng ta có mang lại hiệu quả tích cực hay không.

Ngoài việc thu thập dữ liệu về sự bất ổn của bố cục, hãy xem Báo cáo trải nghiệm người dùng trên Chrome. Báo cáo này bao gồm dữ liệu về Chỉ số CLS dựa trên trải nghiệm thực tế của người dùng trên hàng triệu trang web. Công cụ này giúp bạn biết được hiệu suất của mình (hoặc đối thủ cạnh tranh), hoặc bạn có thể dùng công cụ này để khám phá trạng thái bất ổn về bố cục trên web.