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à chỉ số tổng hợp 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 sẽ rất thú vị nếu bạ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 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 đề.

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ả 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 thời gian và mức độ nghiêm trọng của sự thay đổi sẽ giúp bạn thu hẹp những yếu tố có thể gây ra sự thay đổi đó. Hãy quay lại WebPageTest để có môi trườ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 Instability API (API về sự không ổn định của bố cục) đượ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 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 đó. Lý do là 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 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 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 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 trong 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

Bây giờ, chúng ta đã biết rằng bảng được tạo không đồng bộ đang khiến một phần ba khung nhìn bị dịch chuyển, đã đế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 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 đủ.

Hình thức của phần giữ chỗ mà bạn sử dụng không ảnh hưởng đến độ ổ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.

Dưới đây là hình ảnh trình giữ chỗ trong khi dữ liệu JSON đang tải:

Bảng dữ liệu được kết xuất bằng dữ liệu giữ chỗ.
Bảng dữ liệu được hiển thị bằng 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.
Băng hình WebPageTest cho thấy cả hai trang web đang tải cạnh nhau 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ó 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 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.

(Thêm một điều nữa) Đo lường tình trạng 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. Công cụ này giúp bạn tìm hiểu hiệu suất của mình (hoặc đối thủ cạnh tranh) 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 của bố cục trên web.