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

Hướng dẫn từng bước về 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à tổng hợp của tất cả các lần thay đổi bố cục, vì vậy, trong bài đăng này, tôi nghĩ rằng bạn nên tìm hiểu sâu hơn và kiểm tra từng lần thay đổi bố cục trên một trang để cố gắng tìm hiểu nguyên nhân gây ra sự không ổn định và thực sự cố gắng khắc phục(các) vấn đề.

Bằng cách sử dụng API Không ổn định của bố cục, 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 sẽ tạo ra một mảng các 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, có một sự thay đổi rất nhỏ là 0,01% ở 210 mili giây.

Việc biết được thời gian và mức độ nghiêm trọng của sự thay đổi sẽ rất hữu ích trong việc giúp thu hẹp nguyên nhân có thể dẫn đến sự thay đổi đó. Hãy quay lại WebPageTest trong môi trường phòng thí nghiệm để kiểm thử thêm.

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

Tương tự như việc đo lường CLS trong WebPageTest, bạn cần có một chỉ số tuỳ chỉnh để đo lường từng lần thay đổi bố cục. May mắn là quá trình này hiện đã dễ dàng hơn khi Chrome 77 đã ổn định. Layout Không ổn định API được bật theo mặc định. Vì vậy, bạn có thể thực thi đoạn mã JS đó trên bất kỳ trang web nào 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 phải lo lắng về cờ dòng lệnh hoặ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ời hứa trong tập lệnh này sẽ phân giải thành một bản trình bày 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 các loại dữ liệu gốc như chuỗi hoặc số.

Trang web mà tôi sẽ sử dụng cho thử nghiệm này là ismyhostfastyet.com, một trang web mà tôi đã tạo để so sánh hiệu suất tải thực tế của các nhà cung cấp dịch vụ lưu trữ web.

Xác định nguyên nhân gây ra sự không ổn định của bố cục

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

[
  {
    "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 34,2% xảy ra ở 3087 mili giây. Để xác định nguyên nhân, hãy sử dụng chế độ xem băng hình của WebPageTest.

Hai ô trong băng hình, hiển thị ảnh chụp màn hình trước và sau khi thay đổi bố cục.
Hai ô trong dải phim, hiển thị ảnh chụp màn hình trước và sau khi thay đổi bố cục.

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

Tiêu đề phông chữ trên web xuất hiện không rõ lý do.
Tiêu đề phông chữ trên web xuất hiện không rõ nguyên nhân.

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

Khắc phục sự không ổn định của bố cục

Giờ đây, chúng ta đã biết bảng được tạo không đồng bộ đang khiến một phần ba khung nhìn thay đổi, đã đế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 phần giữ chỗ để bố cục tương đối ổn định khi DOM được hiển thị.

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

Sự xuất hiện của phần giữ chỗ không quan trọng đối với độ ổn định của bố cục. Mục đích của phần giữ chỗ là để đảm bảo với người dùng rằng nội dung sẽ xuất hiện và trang không bị lỗi.

Khi tải dữ liệu JSON, phần giữ chỗ sẽ trông như sau:

Bảng dữ liệu được hiển thị với dữ liệu phần giữ chỗ.
Bảng dữ liệu được hiển thị với dữ liệu phần giữ chỗ.

Việc giải quyết vấn đề phông chữ 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 trong phần khai báo phông chữ, cho phép trình duyệt hiển thị văn bản trong phông chữ dự phòng ngay lập tức. Dưới đây là mã đánh dấu tương ứng đã sửa lỗi:

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

Xác minh các biện pháp tối ưu hoá

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

Băng hình WebPageTest cho thấy cả hai trang web tải cạnh nhau có và không có tính năng tối ưu hoá bố cục.
Cuộn phim WebPageTest cho thấy cả hai trang web tải song song với nhau và không có tính năng 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ó sự thay đổi bố cục xảy ra ở 3071 mili giây (khoảng thời gian tương tự như trước đây) 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.

Cũng có thể thấy rõ từ băng hình rằng phông chữ <h1> ngay lập tức sẽ quay lại phông chữ hệ thống, cho phép người dùng đọc phông chữ đó sớm hơn.

Kết luận

Các trang web phức tạp có thể sẽ trải qua nhiều thay đổi về 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ự không ổn định của bố cục vào WebPageTest, tham chiếu chéo kết quả với băng hình tải hình ảnh để xác định nguyên nhân và triển khai biện pháp khắc phục bằng cách sử dụng phần giữ chỗ để đặt trước không gian màn hình.

(Một điều nữa) Đo lường sự không ổn định của bố cục mà người dùng thực tế 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 thấy chỉ số được cải thiện, nhưng điều thực sự quan trọng là trải nghiệm người dùng thực sự tốt hơn. Đó có phải là lý do chúng tôi đang cố gắng cải thiện trang web ngay từ đầu không?

Vì vậy, thật tuyệt nếu chúng ta bắt đầu đo lường trải nghiệm về độ không ổn định 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 web truyền thống. Đây là một phần quan trọng của vòng lặp phản hồi tối ưu hoá vì dữ liệu từ thực tế cho chúng ta biết vấn đề nằm ở đâu và liệu các biện pháp khắc phục của chúng ta có tạo ra sự khác biệt tích cực hay không.

Ngoài việc thu thập dữ liệu về sự không ổn định 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ề Sự thay đổi bố cục tích luỹ từ trải nghiệm thực tế của người dùng trên hàng triệu trang web. Dữ liệu này giúp bạn tìm hiểu hiệu suất của bạn (hoặc đối thủ cạnh tranh) hoặc sử dụng dữ liệu này để khám phá trạng thái không ổn định của bố cục trên web.