Bộ nhớ đệm cho thao tác tiến/lùi

Bộ nhớ đệm cho thao tác tiến/lùi (hay bfcache) là một tính năng tối ưu hoá trình duyệt, cho phép điều hướng tiến và lùi tức thì. Phiên bản này cải thiện đáng kể trải nghiệm duyệt web, đặc biệt là đối với người dùng có mạng hoặc thiết bị chậm.

Là nhà phát triển web, bạn cần phải hiểu cách tối ưu hoá các trang của bạn cho bfcache để người dùng có thể hưởng lợi.

Khả năng tương thích với trình duyệt

bfcache đã được hỗ trợ trong cả FirefoxSafari trong nhiều năm, trên máy tính và thiết bị di động.

Kể từ phiên bản 86, Chrome đã bật bfcache cho thao tác trên nhiều trang web trên Android cho một tỷ lệ nhỏ người dùng. Trong các bản phát hành tiếp theo, dịch vụ hỗ trợ bổ sung dần được triển khai. Kể từ phiên bản 96, bfcache được bật cho tất cả người dùng Chrome trên máy tính và thiết bị di động.

kiến thức cơ bản về bfcache

bfcache là một bộ nhớ đệm trong bộ nhớ, giúp lưu trữ ảnh chụp nhanh hoàn chỉnh của một trang (bao gồm cả vùng nhớ khối xếp JavaScript) khi người dùng đang di chuyển khỏi đó. Khi toàn bộ trang trong bộ nhớ, trình duyệt có thể nhanh chóng khôi phục trang nếu người dùng quyết định quay lại.

Bạn đã bao nhiêu lần truy cập vào một trang web rồi nhấp vào một đường liên kết để chuyển sang một trang khác, nhưng rồi nhận ra rằng đó không phải là nội dung mình muốn rồi nhấp vào nút quay lại? Tại thời điểm đó, bfcache có thể tạo ra sự khác biệt lớn về tốc độ tải trang trước đó:

Khi không bật bfcache Một yêu cầu mới sẽ được đưa ra để tải trang trước đó. Tuỳ thuộc vào mức độ tối ưu hoá trang đó cho lượt truy cập lặp lại, trình duyệt có thể phải tải xuống lại, phân tích cú pháp và thực thi lại một số (hoặc tất cả) tài nguyên vừa tải xuống.
Khi bật bfcache Quá trình tải trang trước về cơ bản là ngay lập tức, vì toàn bộ trang có thể được khôi phục từ bộ nhớ mà không cần phải chuyển đến mạng.

Hãy xem video về cách hoạt động của bfcache để hiểu rõ tốc độ điều hướng mà bộ nhớ đệm này có thể mang lại:

Việc sử dụng bfcache giúp các trang tải nhanh hơn nhiều trong quá trình điều hướng tiến và lùi.

Trong video, ví dụ có bfcache nhanh hơn một chút so với ví dụ không có bộ nhớ đệm.

bfcache không chỉ tăng tốc độ điều hướng mà còn giảm mức sử dụng dữ liệu vì các tài nguyên không phải tải xuống lại.

Dữ liệu sử dụng Chrome cho thấy rằng 1/10 thao tác điều hướng trên máy tính và 1/5 thao tác trên thiết bị di động là thao tác tiến hoặc lùi. Khi bật bfcache, các trình duyệt có thể loại bỏ việc chuyển dữ liệu và mất thời gian tải cho hàng tỷ trang web mỗi ngày!

Cách hoạt động của "bộ nhớ đệm"

"Bộ nhớ đệm" mà bfcache sử dụng khác với bộ nhớ đệm HTTP, đóng vai trò riêng trong việc tăng tốc các lần điều hướng lặp lại. bfcache là ảnh chụp nhanh của toàn bộ trang trong bộ nhớ, bao gồm cả vùng nhớ khối xếp JavaScript, trong khi bộ nhớ đệm HTTP chỉ chứa phản hồi cho các yêu cầu được đưa ra trước đó. Vì tất cả các yêu cầu bắt buộc phải tải một trang sẽ được thực hiện từ bộ nhớ đệm HTTP, các lượt truy cập lặp lại bằng tính năng khôi phục bfcache luôn nhanh hơn cả các lần điều hướng không phải bfcache được tối ưu hoá tốt nhất.

Tuy nhiên, việc tạo ảnh chụp nhanh của một trang trong bộ nhớ có thể gây ra một số vấn đề phức tạp về cách tốt nhất để bảo toàn đoạn mã đang tiến hành. Ví dụ: bạn xử lý các lệnh gọi setTimeout() khi hết thời gian chờ trong khi trang đang nằm trong bfcache như thế nào?

Câu trả lời là các trình duyệt sẽ tạm dừng mọi đồng hồ hẹn giờ đang chờ xử lý hoặc lời hứa chưa được giải quyết cho các trang trong bfcache, bao gồm hầu hết mọi tác vụ đang chờ xử lý trong hàng đợi tác vụ JavaScript và tiếp tục xử lý các tác vụ nếu trang đó được khôi phục từ bfcache.

Trong một số trường hợp, chẳng hạn như đối với thời gian chờ và lời hứa, đây là rủi ro khá thấp, nhưng cũng có thể dẫn đến hành vi khó hiểu hoặc không mong muốn. Ví dụ: nếu trình duyệt tạm dừng một tác vụ cần thiết trong giao dịch IndexedDB, thì tác vụ đó có thể ảnh hưởng đến các thẻ đang mở khác trong cùng một nguồn gốc, vì cùng một cơ sở dữ liệu IndexedDB có thể được nhiều thẻ truy cập đồng thời. Do đó, các trình duyệt thường sẽ không cố gắng lưu các trang vào bộ nhớ đệm khi đang tiến hành giao dịch IndexedDB hoặc trong khi sử dụng các API có thể ảnh hưởng đến các trang khác.

Để biết thêm thông tin chi tiết về mức độ ảnh hưởng của các cách sử dụng API khác nhau đến tính đủ điều kiện của bfcache của trang, hãy xem Tối ưu hoá các trang của bạn cho bfcache.

bfcache và iframe

Nếu một trang chứa iframe được nhúng thì bản thân các iframe đó không đủ điều kiện để dùng bfcache. Ví dụ: nếu bạn điều hướng đến một trang khác trong iframe, nhưng sau đó quay lại, trình duyệt sẽ "quay lại" trong iframe thay vì trong khung chính, nhưng thao tác điều hướng quay lại trong iframe sẽ không sử dụng bfcache.

Khung chính cũng có thể bị chặn sử dụng bfcache nếu iframe được nhúng sử dụng API chặn khung này. Bạn có thể sử dụng Chính sách về quyền được thiết lập trên khung chính hoặc việc sử dụng thuộc tính sandbox để tránh điều này.

Bộ nhớ đệm và ứng dụng trang đơn (SPA)

Vì bfcache hoạt động với các thao tác điều hướng do trình duyệt quản lý, nên bfcache không hoạt động trong "thao tác mềm" trong ứng dụng trang đơn (SPA). Tuy nhiên, bfcache vẫn có thể hữu ích khi quay lại SPA thay vì khởi chạy lại toàn bộ ứng dụng đó từ đầu.

Các API để quan sát bfcache

Mặc dù bfcache là một tính năng tối ưu hoá mà các trình duyệt tự động thực hiện, nhưng nhà phát triển vẫn cần biết được thời điểm xảy ra để họ có thể tối ưu hoá trang cho phù hợpđiều chỉnh mọi chỉ số hoặc kết quả đo lường hiệu suất cho phù hợp.

Các sự kiện chính dùng để ghi nhận bfcache là sự kiện chuyển đổi trang pageshowpagehide. hầu hết các trình duyệt đều hỗ trợ các sự kiện này.

Các sự kiện Vòng đời trang mới hơn – freezeresume – cũng được gửi đi khi các trang truy cập hoặc rời khỏi bfcache, cũng như trong một số trường hợp khác, chẳng hạn như khi một thẻ trong nền bị treo để giảm thiểu mức sử dụng CPU. Những sự kiện này chỉ được hỗ trợ trong các trình duyệt dựa trên Chromium.

Quan sát thời điểm một trang được khôi phục từ bfcache

Sự kiện pageshow sẽ kích hoạt ngay sau sự kiện load khi trang đang tải ban đầu và mỗi khi trang được khôi phục từ bfcache. Sự kiện pageshow có một thuộc tính persisted, là true nếu trang được khôi phục từ bfcache và nếu không thì false. Bạn có thể sử dụng thuộc tính persisted để phân biệt lượt tải trang thông thường với lượt khôi phục bfcache. Ví dụ:

window.addEventListener('pageshow', (event) => {
  if (event.persisted) {
    console.log('This page was restored from the bfcache.');
  } else {
    console.log('This page was loaded normally.');
  }
});

Trong các trình duyệt hỗ trợ Page Lifecycle API, sự kiện resume sẽ kích hoạt khi các trang được khôi phục từ bfcache (ngay trước sự kiện pageshow) và khi người dùng truy cập lại vào một thẻ nền đã bị treo. Nếu muốn cập nhật trạng thái của một trang sau khi trang đó bị treo (bao gồm cả các trang trong bfcache), bạn có thể sử dụng sự kiện resume. Tuy nhiên, nếu muốn đo tỷ lệ truy cập bfcache của trang web thì bạn cần sử dụng sự kiện pageshow. Trong một số trường hợp, bạn có thể cần sử dụng cả hai.

Để biết thông tin chi tiết về các phương pháp hay nhất khi đo lường bfcache, hãy xem bài viết Cách bfcache ảnh hưởng đến phân tích và đo lường hiệu suất.

Quan sát khi một trang chuyển vào bfcache

Sự kiện pagehide sẽ kích hoạt khi một trang huỷ tải hoặc khi trình duyệt cố gắng đưa trang đó vào bfcache.

Sự kiện pagehide cũng có một thuộc tính persisted. Nếu là false, bạn có thể yên tâm rằng trang đó sẽ không vào bfcache. Tuy nhiên, việc persistedtrue không đảm bảo rằng một trang sẽ được lưu vào bộ nhớ đệm. Điều này có nghĩa là trình duyệt intends lưu trang vào bộ nhớ đệm, nhưng có thể có các yếu tố khác khiến trình duyệt không thể lưu vào bộ nhớ đệm.

window.addEventListener('pagehide', (event) => {
  if (event.persisted) {
    console.log('This page *might* be entering the bfcache.');
  } else {
    console.log('This page will unload normally and be discarded.');
  }
});

Tương tự, sự kiện freeze sẽ kích hoạt ngay sau sự kiện pagehide nếu persistedtrue, nhưng điều đó chỉ có nghĩa là trình duyệt intends lưu trang vào bộ nhớ đệm. Tài khoản này có thể vẫn phải loại bỏ tài khoản vì một số lý do sẽ được giải thích sau này.

Tối ưu hoá các trang của bạn cho bfcache

Không phải trang nào cũng được lưu trữ trong bfcache và ngay cả khi một trang được lưu trữ ở đó, nó sẽ không ở đó vô thời hạn. Điều quan trọng là nhà phát triển phải hiểu được điều gì khiến các trang đủ điều kiện (và không đủ điều kiện) cho bfcache để tối đa hoá tỷ lệ truy cập vào bộ nhớ đệm.

Các phần sau đây trình bày các phương pháp hay nhất để giúp trình duyệt có thể lưu các trang của bạn vào bộ nhớ đệm nhiều nhất có thể.

Không bao giờ sử dụng sự kiện unload

Cách quan trọng nhất để tối ưu hoá bfcache trên mọi trình duyệt là tuyệt đối không sử dụng sự kiện unload. Chưa từng có!

Sự kiện unload gây ra vấn đề cho trình duyệt vì sự kiện này ra mắt trước bfcache và nhiều trang trên Internet hoạt động theo giả định (hợp lý) rằng một trang sẽ không tiếp tục tồn tại sau khi sự kiện unload kích hoạt. Điều này đặt ra một thách thức vì nhiều trang trong số đó cũng được xây dựng với giả định rằng sự kiện unload sẽ kích hoạt bất cứ khi nào người dùng rời đi. Điều này không còn đúng nữa (và đã không còn đúng trong một thời gian dài).

Vì vậy, các trình duyệt đang gặp phải một tình huống khó xử, phải lựa chọn giữa cách nào đó có thể cải thiện trải nghiệm người dùng, nhưng cũng có nguy cơ gây hỏng trang.

Trên máy tính, Chrome và Firefox đã chọn cách khiến các trang không đủ điều kiện để lưu vào bộ nhớ đệm nếu thêm trình nghe unload. Cách này ít rủi ro hơn nhưng cũng khiến nhiều trang bị loại. Safari sẽ cố gắng lưu một số trang vào bộ nhớ đệm bằng trình nghe sự kiện unload. Tuy nhiên, để giảm khả năng hỏng hóc, sự kiện unload sẽ không chạy khi người dùng rời đi, điều này khiến sự kiện này rất không đáng tin cậy.

Trên thiết bị di động, Chrome và Safari sẽ cố gắng lưu các trang vào bộ nhớ đệm bằng trình nghe sự kiện unload vì nguy cơ bị hỏng sẽ thấp hơn do sự kiện unload luôn cực kỳ không đáng tin cậy trên thiết bị di động. Firefox coi các trang sử dụng unload là không đủ điều kiện cho bfcache, ngoại trừ trên iOS, vì các trang này yêu cầu tất cả trình duyệt phải sử dụng công cụ kết xuất WebKit và vì vậy nó hoạt động giống như Safari.

Thay vì sử dụng sự kiện unload, hãy sử dụng sự kiện pagehide. Sự kiện pagehide sẽ kích hoạt trong mọi trường hợp mà sự kiện unload kích hoạt, đồng thời cũng sẽ kích hoạt khi một trang được đưa vào bộ nhớ đệm cho thao tác tiến/lùi.

Trên thực tế, Lighthouse có một quy trình kiểm tra no-unload-listeners. Công cụ này sẽ cảnh báo nhà phát triển nếu có bất kỳ JavaScript nào trên các trang của họ (bao gồm cả JavaScript từ thư viện của bên thứ ba) thêm một trình nghe sự kiện unload.

Do tính không tin cậy và tác động đến hiệu suất của bfcache, Chrome đang tìm cách ngừng sử dụng sự kiện unload.

Sử dụng Chính sách về quyền để ngăn việc sử dụng trình xử lý huỷ tải trên một trang

Các trang web không dùng trình xử lý sự kiện unload có thể đảm bảo rằng những trình xử lý này sẽ không được thêm vào bằng cách sử dụng Chính sách về quyền trên Chrome 115.

Permission-Policy: unload()

Việc này cũng ngăn bên thứ ba hoặc tiện ích làm chậm trang web bằng cách thêm các trình xử lý huỷ tải và khiến trang web không đủ điều kiện để dùng bfcache.

Chỉ thêm trình nghe beforeunload theo điều kiện

Sự kiện beforeunload sẽ không khiến các trang của bạn không đủ điều kiện để dùng bfcache trong các trình duyệt hiện đại, nhưng trước đây nó vẫn không đáng tin cậy và vẫn không đáng tin cậy, vì vậy hãy tránh sử dụng bfcache trừ phi thực sự cần thiết.

Tuy nhiên, không giống như sự kiện unload, beforeunload được sử dụng hợp pháp. Ví dụ: khi bạn muốn cảnh báo người dùng rằng họ sẽ mất các thay đổi chưa lưu nếu rời khỏi trang. Trong trường hợp này, bạn chỉ nên thêm trình nghe beforeunload khi người dùng chưa lưu các thay đổi, rồi xoá các thay đổi đó ngay sau khi lưu các thay đổi chưa lưu.

Không nên
window.addEventListener('beforeunload', (event) => {
  if (pageHasUnsavedChanges()) {
    event.preventDefault();
    return event.returnValue = 'Are you sure you want to exit?';
  }
});
Mã này sẽ thêm một trình nghe beforeunload vô điều kiện.
Nên
function beforeUnloadListener(event) {
  event.preventDefault();
  return event.returnValue = 'Are you sure you want to exit?';
};

// A function that invokes a callback when the page has unsaved changes.
onPageHasUnsavedChanges(() => {
  window.addEventListener('beforeunload', beforeUnloadListener);
});

// A function that invokes a callback when the page's unsaved changes are resolved.
onAllChangesSaved(() => {
  window.removeEventListener('beforeunload', beforeUnloadListener);
});
Mã này chỉ thêm trình nghe beforeunload khi cần thiết (và xoá trình nghe khi không cần thiết).

Giảm thiểu việc sử dụng Cache-Control: no-store

Cache-Control: no-store là một tiêu đề HTTP mà các máy chủ web có thể đặt đối với các phản hồi hướng dẫn trình duyệt không lưu trữ phản hồi trong bất kỳ bộ nhớ đệm HTTP nào. Được dùng cho các tài nguyên chứa thông tin nhạy cảm của người dùng, chẳng hạn như các trang yêu cầu đăng nhập.

Mặc dù bfcache không phải là bộ nhớ đệm HTTP, nhưng trước đây, khi đặt Cache-Control: no-store trên chính tài nguyên trang (trái ngược với mọi tài nguyên phụ), các trình duyệt đã chọn không lưu trữ trang trong bfcache. Đang tiến hành thay đổi hành vi này cho Chrome theo cách bảo đảm quyền riêng tư, nhưng hiện tại mọi trang sử dụng Cache-Control: no-store đều sẽ không đủ điều kiện dùng bộ nhớ đệm cho thao tác tiến/lùi.

Cache-Control: no-store hạn chế một trang đủ điều kiện để dùng bfcache, nên bạn chỉ nên thiết lập trang này trên những trang có chứa thông tin nhạy cảm. Việc lưu vào bộ nhớ đệm dưới bất kỳ hình thức nào là không phù hợp.

Đối với các trang cần luôn phân phát nội dung mới nhất và nội dung không chứa thông tin nhạy cảm, hãy sử dụng Cache-Control: no-cache hoặc Cache-Control: max-age=0. Những lệnh này hướng dẫn trình duyệt xác thực lại nội dung trước khi phân phát và không ảnh hưởng đến điều kiện bfcache của trang.

Lưu ý rằng khi một trang được khôi phục từ bfcache, trang đó sẽ được khôi phục từ bộ nhớ chứ không phải từ bộ nhớ đệm HTTP. Do đó, các lệnh như Cache-Control: no-cache hoặc Cache-Control: max-age=0 không được xem xét và không có quá trình xác thực lại nào xảy ra trước khi hiển thị nội dung cho người dùng.

Đây vẫn có thể là trải nghiệm người dùng tốt hơn, tuy nhiên, vì quá trình khôi phục bfcache diễn ra ngay lập tức và vì các trang không nằm trong bfcache quá lâu nên nội dung cũng ít có khả năng bị lỗi thời. Tuy nhiên, nếu nội dung của bạn thay đổi theo từng phút, bạn có thể tìm nạp nội dung cập nhật bằng sự kiện pageshow, như trình bày trong phần tiếp theo.

Cập nhật dữ liệu cũ hoặc nhạy cảm sau khi khôi phục bfcache

Nếu trang web của bạn giữ trạng thái người dùng — đặc biệt là bất kỳ thông tin nhạy cảm nào của người dùng — thì dữ liệu đó cần được cập nhật hoặc xoá sau khi trang được khôi phục từ bfcache.

Ví dụ: nếu người dùng điều hướng đến một trang thanh toán rồi cập nhật giỏ hàng, thì thao tác quay lại có khả năng hiển thị thông tin lỗi thời nếu một trang cũ được khôi phục từ bfcache.

Một ví dụ khác quan trọng hơn là khi người dùng đăng xuất khỏi trang web trên máy tính công cộng và người dùng tiếp theo nhấp vào nút quay lại. Việc này có khả năng làm lộ dữ liệu riêng tư mà người dùng cho rằng đã bị xoá khi họ đăng xuất.

Để tránh những trường hợp như vậy, bạn nên luôn cập nhật trang sau sự kiện pageshow nếu event.persistedtrue:

window.addEventListener('pageshow', (event) => {
  if (event.persisted) {
    // Do any checks and updates to the page
  }
});

Tốt nhất là bạn nên cập nhật nội dung, nhưng đối với một số thay đổi, bạn nên buộc tải lại toàn bộ. Mã sau đây sẽ kiểm tra sự hiện diện của cookie của riêng trang web trong sự kiện pageshow và tải lại nếu không tìm thấy cookie đó:

window.addEventListener('pageshow', (event) => {
  if (event.persisted && !document.cookie.match(/my-cookie)) {
    // Force a reload if the user has logged out.
    location.reload();
  }
});

Tải lại có lợi thế là vẫn giữ nguyên lịch sử (để cho phép điều hướng tiến), nhưng chuyển hướng có thể phù hợp hơn trong một số trường hợp.

Khôi phục quảng cáo và bộ nhớ đệm

Bạn có thể muốn tránh sử dụng bfcache để phân phát một nhóm quảng cáo mới trên mỗi lần điều hướng tiến/lùi. Tuy nhiên, bên cạnh việc tác động đến hiệu suất, người ta đặt câu hỏi liệu những hành vi như vậy có giúp tăng mức độ tương tác với quảng cáo hay không. Người dùng có thể đã nhận thấy quảng cáo mà họ định quay lại nhấp vào nhưng bằng cách tải lại thay vì khôi phục từ bfcache mà họ không thể truy cập. Việc thử nghiệm tình huống này (tốt nhất là bằng thử nghiệm A/B) là rất quan trọng trước khi đưa ra các giả định.

Đối với các trang web muốn làm mới quảng cáo khi khôi phục bfcache, việc chỉ làm mới quảng cáo trên sự kiện pageshow khi event.persistedtrue sẽ cho phép điều này xảy ra mà không ảnh hưởng đến hiệu suất của trang. Hãy liên hệ với nhà cung cấp quảng cáo của bạn, nhưng đây là một ví dụ về cách thực hiện việc này với Thẻ xuất bản của Google.

Tránh tham chiếu window.opener

Trong các trình duyệt cũ, nếu bạn mở một trang bằng window.open() qua đường liên kết có target=_blank mà không chỉ định rel="noopener", thì trang mở sẽ tham chiếu đến đối tượng cửa sổ của trang đã mở.

Ngoài việc này là rủi ro bảo mật, bạn không thể đặt một trang có tệp tham chiếu window.opener có giá trị null vào bfcache vì như vậy có thể làm hỏng bất kỳ trang nào tìm cách truy cập vào đó.

Do đó, tốt nhất bạn nên tránh tạo tệp tham chiếu window.opener. Bạn có thể thực hiện việc này bằng cách sử dụng rel="noopener" bất cứ khi nào có thể (lưu ý rằng đây là chế độ mặc định trong tất cả các trình duyệt hiện đại). Nếu trang web của bạn yêu cầu mở một cửa sổ và kiểm soát cửa sổ thông qua window.postMessage() hoặc tham chiếu trực tiếp đối tượng cửa sổ, thì cả cửa sổ đang mở lẫn trình mở đều không đủ điều kiện dùng bfcache.

Đóng các kết nối đang mở trước khi người dùng rời đi

Như đã đề cập trước đó, khi một trang được đưa vào bfcache, nó sẽ tạm dừng tất cả các tác vụ JavaScript đã lên lịch và tiếp tục chúng khi trang được lấy ra khỏi bộ nhớ đệm.

Nếu các tác vụ JavaScript đã lên lịch này chỉ truy cập vào API DOM (hoặc các API khác được tách riêng với trang hiện tại) thì việc tạm dừng các tác vụ này trong khi trang không hiển thị cho người dùng sẽ không gây ra bất kỳ sự cố nào.

Tuy nhiên, nếu các tác vụ này được kết nối với các API cũng có thể truy cập được từ các trang khác trong cùng một nguồn gốc (ví dụ: IndexedDB, Web Locks, WebSockets) thì điều này có thể gây ra sự cố vì việc tạm dừng các tác vụ này có thể ngăn mã trong các thẻ khác chạy.

Do đó, một số trình duyệt sẽ không tìm cách đặt một trang vào bfcache trong các trường hợp sau:

Nếu trang của bạn đang sử dụng bất kỳ API nào trong số này, bạn nên đóng các kết nối và xoá hoặc ngắt kết nối đối tượng tiếp nhận dữ liệu trong sự kiện pagehide hoặc freeze. Điều đó cho phép trình duyệt lưu trang vào bộ nhớ đệm một cách an toàn mà không có nguy cơ ảnh hưởng đến các thẻ đang mở khác.

Sau đó, nếu trang được khôi phục từ bfcache, bạn có thể mở lại hoặc kết nối lại với các API đó trong sự kiện pageshow hoặc resume.

Ví dụ sau cho thấy cách đảm bảo các trang sử dụng IndexedDB đủ điều kiện sử dụng bfcache bằng cách đóng một kết nối mở trong trình nghe sự kiện pagehide:

let dbPromise;
function openDB() {
  if (!dbPromise) {
    dbPromise = new Promise((resolve, reject) => {
      const req = indexedDB.open('my-db', 1);
      req.onupgradeneeded = () => req.result.createObjectStore('keyval');
      req.onerror = () => reject(req.error);
      req.onsuccess = () => resolve(req.result);
    });
  }
  return dbPromise;
}

// Close the connection to the database when the user leaves.
window.addEventListener('pagehide', () => {
  if (dbPromise) {
    dbPromise.then(db => db.close());
    dbPromise = null;
  }
});

// Open the connection when the page is loaded or restored from bfcache.
window.addEventListener('pageshow', () => openDB());

Kiểm tra để đảm bảo các trang của bạn có thể lưu vào bộ nhớ đệm

Công cụ của Chrome cho nhà phát triển có thể giúp bạn thử nghiệm các trang của bạn để đảm bảo các trang đó được tối ưu hoá cho bfcache và xác định mọi vấn đề có thể khiến các trang đó không đủ điều kiện.

Cách kiểm tra một trang:

  1. Chuyển đến trang đó trong Chrome.
  2. Trong Công cụ cho nhà phát triển, hãy chuyển đến Ứng dụng -> Bộ nhớ đệm cho thao tác tiến/lùi.
  3. Nhấp vào nút Run Test (Chạy phép kiểm thử). Sau đó, Công cụ cho nhà phát triển sẽ cố gắng chuyển sang phần khác và quay lại để xác định xem có thể khôi phục trang từ bfcache hay không.
Bảng điều khiển bộ nhớ đệm cho thao tác tiến/lùi trong Công cụ cho nhà phát triển
Bảng Bộ nhớ đệm cho thao tác tiến/lùi trong Công cụ cho nhà phát triển.

Nếu kiểm tra thành công, bảng điều khiển sẽ báo cáo "Đã khôi phục từ bộ nhớ đệm cho thao tác tiến/lùi".

Đã khôi phục thành công trang báo cáo Công cụ cho nhà phát triển từ bfcache
Trang đã được khôi phục thành công.

Nếu không thành công, bảng điều khiển sẽ cho biết lý do. Nếu lý do là vấn đề bạn có thể giải quyết với tư cách là nhà phát triển, thì bảng điều khiển sẽ đánh dấu lý do đó là Có thể hành động.

Lỗi báo cáo Công cụ cho nhà phát triển không khôi phục được trang từ bfcache
Thử nghiệm bfcache không thành công và cho ra kết quả hữu ích.

Trong ví dụ này, việc sử dụng trình nghe sự kiện unload sẽ khiến trang không đủ điều kiện để dùng bfcache. Bạn có thể khắc phục vấn đề này bằng cách chuyển từ unload sang pagehide:

Nên
window.addEventListener('pagehide', ...);
Không nên
window.addEventListener('unload', ...);

Lighthouse 10.0 cũng đã thêm tính năng kiểm tra bfcache, thực hiện thử nghiệm tương tự. Để biết thêm thông tin, hãy xem tài liệu về kiểm tra bfcache.

Cách bfcache ảnh hưởng đến số liệu phân tích và đo lường hiệu suất

Nếu sử dụng công cụ phân tích để đo lường lượt truy cập vào trang web của mình, thì bạn có thể nhận thấy tổng số lượt xem trang được báo cáo giảm vì Chrome bật bfcache cho nhiều người dùng hơn.

Trên thực tế, có thể bạn đã báo cáo thiếu số lượt xem trang từ các trình duyệt khác có triển khai bfcache, vì nhiều thư viện phân tích phổ biến không đo lường số lượt khôi phục bfcache dưới dạng lượt xem trang mới.

Để đưa số lượt khôi phục bfcache vào số lượt xem trang, hãy đặt trình nghe cho sự kiện pageshow và kiểm tra tài sản persisted.

Ví dụ sau cho thấy cách thực hiện việc này với Google Analytics. Các công cụ phân tích khác có thể sử dụng logic tương tự:

// Send a pageview when the page is first loaded.
gtag('event', 'page_view');

window.addEventListener('pageshow', (event) => {
  // Send another pageview if the page is restored from bfcache.
  if (event.persisted) {
    gtag('event', 'page_view');
  }
});

Đo lường tỷ lệ truy cập bfcache của bạn

Bạn cũng có thể đo lường xem bfcache đã được sử dụng hay chưa, để giúp xác định các trang không sử dụng bfcache. Điều này có thể thực hiện được bằng cách đo lường loại điều hướng cho các lượt tải trang:

// Send a navigation_type when the page is first loaded.
gtag('event', 'page_view', {
   'navigation_type': performance.getEntriesByType('navigation')[0].type;
});

window.addEventListener('pageshow', (event) => {
  if (event.persisted) {
    // Send another pageview if the page is restored from bfcache.
    gtag('event', 'page_view', {
      'navigation_type': 'back_forward_cache';
    });
  }
});

Tính tỷ lệ truy cập bfcache bằng cách sử dụng số lần điều hướng back_forward và điều hướng back_forward_cache.

Xin lưu ý rằng có một số trường hợp nằm ngoài quyền kiểm soát của chủ sở hữu trang web khi thao tác điều hướng Tiến/lùi không sử dụng bfcache, bao gồm:

  • khi người dùng thoát khỏi trình duyệt và khởi động lại
  • khi người dùng sao chép một thẻ
  • khi người dùng đóng một thẻ rồi mở lại

Trong một vài trường hợp, loại điều hướng gốc có thể được một số trình duyệt giữ nguyên và do đó, có thể hiển thị loại back_forward mặc dù những điều hướng này không phải là điều hướng Quay lại/Tiến.

Ngay cả khi không có các loại trừ đó, bfcache sẽ bị loại bỏ sau một khoảng thời gian để bảo toàn bộ nhớ.

Vì vậy, chủ sở hữu trang web không nên kỳ vọng tỷ lệ truy cập bfcache là 100% cho tất cả các thao tác điều hướng back_forward. Tuy nhiên, việc đo lường tỷ lệ của chúng có thể hữu ích để xác định những trang mà chính trang đó đang ngăn việc sử dụng bfcache để có tỷ lệ điều hướng tiến và lùi cao.

Nhóm Chrome đã thêm NotRestoredReasons API để giúp chỉ ra lý do các trang không sử dụng bfcache, nhờ đó nhà phát triển có thể cải thiện tỷ lệ truy cập bfcache của họ. Nhóm Chrome cũng thêm các loại điều hướng vào CrUX để có thể xem số lượng thao tác bfcache ngay cả khi không tự đo lường.

Đo lường hiệu suất

bfcache cũng có thể ảnh hưởng tiêu cực đến các chỉ số hiệu suất được thu thập tại trường, cụ thể là các chỉ số đo lường thời gian tải trang.

Vì các thao tác điều hướng bfcache khôi phục trang hiện có thay vì bắt đầu tải trang mới, tổng số lượt tải trang được thu thập sẽ giảm khi bfcache được bật. Tuy nhiên, điều quan trọng là tải trang được thay thế bằng tính năng khôi phục bfcache có thể là một trong những trang tải nhanh nhất trong tập dữ liệu của bạn. Điều này là do quá trình điều hướng tiến và lùi (theo định nghĩa) là lượt truy cập lặp lại và tải trang lặp lại thường nhanh hơn tải trang từ khách truy cập lần đầu (do lưu vào bộ nhớ đệm HTTP, như đã đề cập trước đó).

Kết quả là trang tải nhanh trong tập dữ liệu của bạn ít hơn, có thể sẽ làm lệch phân phối chậm hơn, mặc dù hiệu suất mà người dùng trải nghiệm có thể đã được cải thiện!

Có một vài cách để xử lý vấn đề này. Một là chú thích tất cả các chỉ số tải trang bằng loại điều hướng tương ứng: navigate, reload, back_forward hoặc prerender. Nhờ đó, bạn có thể tiếp tục theo dõi hiệu suất trong các loại điều hướng này, ngay cả khi mức phân phối tổng thể có xu hướng tiêu cực. Bạn nên sử dụng phương pháp này cho các chỉ số tải trang không tập trung vào người dùng như Thời gian cho byte đầu tiên (TTFB).

Đối với các chỉ số tập trung vào người dùng như Các chỉ số quan trọng về trang web, bạn nên báo cáo một giá trị thể hiện chính xác hơn trải nghiệm người dùng.

Tác động đến Các chỉ số quan trọng về trang web

Các chỉ số quan trọng về trang web đo lường trải nghiệm của người dùng trên một trang web ở nhiều phương diện (tốc độ tải, tính tương tác, độ ổn định về hình ảnh). Do người dùng trải nghiệm bfcache khôi phục tốc độ chuyển hướng nhanh hơn so với tải toàn trang nên các chỉ số quan trọng về trang web phải phản ánh được điều này. Suy cho cùng, người dùng không quan tâm đến việc liệu bfcache đã được bật hay chưa, họ chỉ quan tâm rằng điều hướng thật nhanh!

Những công cụ thu thập và báo cáo về các chỉ số Các chỉ số quan trọng về trang web (như Báo cáo trải nghiệm người dùng trên Chrome) coi các lượt khôi phục bfcache là các lượt truy cập trang riêng biệt trong tập dữ liệu của công cụ. Và mặc dù không có API hiệu suất web chuyên dụng để đo lường những chỉ số này sau khi bfcache khôi phục, nhưng bạn có thể ước tính giá trị của chúng bằng cách sử dụng API web hiện có:

Để biết thêm thông tin về ảnh hưởng của bfcache ảnh hưởng đến từng chỉ số, hãy xem các trang hướng dẫn về chỉ số cho Các chỉ số quan trọng chính của trang web. Để xem ví dụ cụ thể về cách triển khai phiên bản bfcache của những chỉ số này, hãy tham khảo bài viết PR thêm chúng vào thư viện web-vitals JS.

Thư viện JavaScript web-vitals hỗ trợ khôi phục bfcache trong các chỉ số mà nó báo cáo.

Nguồn thông tin khác