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ề tính không ổn định về bố cục.

Trong 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 tất cả các thay đổi về bố cục, vì vậy, trong bài đăng này, tôi nghĩ sẽ rất thú vị khi tìm hiểu sâu hơn và kiểm tra từng lần thay đổi bố cục riêng lẻ trên một trang để cố gắng tìm hiểu điều gì có thể gây ra sự bất ổn định và thực sự cố gắng khắc phục(các) vấn đề này.

Đ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 thay đổi bố cục không đứng sau sự kiện đầu vào:

[
  {
    "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ự dịch chuyển rất nhỏ 0,01% ở 210 mili giây.

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

Đo lường sự 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 thay đổi về bố cục sẽ yêu cầu bạn phải sử dụng chỉ số tuỳ chỉnh. Rất may là quy trình này nay đã dễ dàng hơn vì Chrome 77 đã ổ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 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 và không phải lo lắng về cờ hiệu 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 chỉ số tùy 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ẽ được giải quyết thành biểu diễn 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 để thử nghiệm là ismyhostfastyet.com, một trang web mà tôi đã xây dựng để so sánh hiệu suất tải trong thực tế của các máy chủ web.

Xác định nguyên nhân gây ra sự bất ổn định 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 sự thay đổi bố cục là 34,2% xảy ra ở 3087 mili giây. Để giúp xác định thủ phạm, hãy sử dụng chế độ xem cuộn phim của WebPageTest.

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

Cuộn đến dấu 3 giây trong cuộn phim sẽ cho chúng ta thấy chính xác nguyên nhân dẫn đến sự thay đổi bố cục 34% là: chiếc bàn 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 này dưới dạng một bảng. Ban đầu bảng trống nên việc chờ điền sẵn khi kết quả được tải là nguyên nhân dẫn đến sự thay đổi.

Tiêu đề phông chữ web xuất hiện từ đâu đó.
Tiêu đề phông chữ trên web xuất hiện từ đâu đó.

Nhưng đó chưa phải là tất cả. Khi trang hoàn tất ở 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 có nhanh không?" xuất hiện từ đâu. Điều này xảy ra vì trang web sử dụng phông chữ trên web và chưa thực hiện bất kỳ bước nào để tối ưu hoá việc hiển thị. Bố cục có vẻ như 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 chờ quá lâu để đọc tiêu đề.

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

Bây giờ, chúng ta đã biết bảng được tạo không đồng bộ đang khiến 1/3 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 thực sự tải kết quả JSON, nhưng chúng ta vẫn có thể điền sẵn vào bảng 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 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. Ký tự "█" lặp lại một số lần ngẫu nhiên để tạo phần giữ chỗ hình ảnh cho văn bản và phân phối 3 giá trị chính được tạo ngẫu nhiên. Tôi cũng đã thêm một số kiểu để khử bão hoà tất cả màu từ bảng để làm rõ rằng dữ liệu chưa được tải đầy đủ.

Hình thức của phần giữ chỗ mà bạn sử dụng không ảnh hưởng đến tính ổ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 đang xuất hiện và trang không bị hỏng.

Dưới đây là giao diện của phần giữ chỗ khi dữ liệu JSON đang tải:

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

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

Xác minh tính năng tối ưu hoá

Sau khi chạy lại trang thông qua WebPageTest, chúng tôi có thể tạo phép 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 về bố cục:

Cuộn phim WebPageTest cho thấy cả hai trang web đang tải song song khi có và không có tính năng tối ưu hoá bố cục.
Cuộn phim WebPageTest cho thấy cả trang web tải song song khi có 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ó một sự thay đổi bố cục diễn ra ở 3071 mili giây (tương đương với 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ể sống với điều này.

Ngoài ra, trên cuộn phim cũng cho thấy rõ rằng phông chữ <h1> sẽ ngay lập tức 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 lần thay đổi bố cục hơn so với ví dụ này, nhưng quá trình khắc phục vẫn giống nhau: thêm chỉ số không ổn định về bố cục vào WebPageTest, tham chiếu chéo kết quả với cuộn phim tải trực quan để xác định thủ phạm và triển khai bản sửa lỗi 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ự bất ổn định về 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á và thấy được sự cải thiện đối với chỉ số, nhưng điều thực sự quan trọng là trải nghiệm người dùng thực sự đang tốt hơn. Đó không phải là lý do chúng tôi cố gắng cải thiện trang web ngay từ đầu sao?

Vì vậy, điều tuyệt vời hơn là chúng ta có thể bắt đầu đo lường trải nghiệm không ổn định về bố cục của người dùng thực tế 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ì việc có dữ liệu từ hiện trường sẽ cho chúng tôi biết vấn đề nằm ở đâu và liệu các bản sửa lỗi của chúng tôi 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ề độ ổn định của bố cục của riêng bạn, hãy xem Báo cáo trải nghiệm người dùng của Chrome. Báo cáo này bao gồm dữ liệu Tổng hợp về mức thay đổi bố cục từ trải nghiệm thực tế của người dùng trên hàng triệu trang web. Tính năng này cho phép bạn tìm hiểu hiệu suất của bạn (hoặc đối thủ cạnh tranh của bạn) hoặc bạn có thể sử dụng công cụ này để khám phá trạng thái không ổn định về bố cục trên web.