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. Cải thiện đáng kể trải nghiệm duyệt web, đặc biệt đối với người dùng có mạng hoặc thiết bị chậm hơn.

Là nhà phát triển web, bạn cần hiểu cách tối ưu hoá các trang của bạn để dùng bfcache, nhờ đó 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 để bàn và thiết bị di động.

Kể từ phiên bản 86, Chrome đã bật bfcache để điều hướng nhiều trang web trong Android cho một tỷ lệ nhỏ người dùng. Trong các bản phát hành tiếp theo, chúng tôi từng bước ra mắt các tính năng hỗ trợ bổ sung. 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.

thông tin cơ bản về bfcache

bfcache là một bộ nhớ đệm trong bộ nhớ lưu trữ toàn bộ ảnh chụp nhanh của trang (bao gồm cả vùng nhớ khối xếp JavaScript) khi người dùng di chuyển khỏi đó. Với 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 đã truy cập vào một trang web bao nhiêu lần và nhấp vào đường liên kết để chuyển đến một trang khác, nhưng rồi bạn nhận ra đó không phải là trang web 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 đó:

Nếu không bật bfcache Yêu cầu mới được khởi tạo để tải trang trước và tuỳ thuộc vào mức độ trang đó được tối ưu hoá cho các lượt truy cập lặp lại, trình duyệt có thể phải tải xuống, phân tích cú pháp lại 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 Việc 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 kết nối mạng.

Xem video này về cách hoạt động của bfcache để hiểu được tốc độ của bộ nhớ đệm trong điều hướng:

Việc sử dụng bfcache giúp 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ó.

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ì không cần phải tải xuống lại tài nguyên.

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

Cách "bộ nhớ đệm" công việc

"Bộ nhớ đệm" do bfcache sử dụng khác với bộ nhớ đệm HTTP, vốn đóng vai trò riêng trong việc tăng tốc các thao tác 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 các phản hồi cho các yêu cầu đã tạo trước đó. Vì rất hiếm khi xảy ra tất cả các yêu cầu tải một trang để được thực hiện từ bộ nhớ đệm HTTP, nên các lượt truy cập lặp lại bằng cách sử dụng khôi phục bfcache luôn nhanh hơn kể cả các thao tác đ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ó đôi chút phức tạp về cách tốt nhất để lưu giữ mã đang tiến hành. Ví dụ: Làm thế nào để bạn xử lý các lệnh gọi setTimeout() khi hết thời gian chờ khi trang đang nằm trong bfcache?

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 các 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 trường hợp hết thời gian chờ và đã hứa hẹn, rủi ro tương đối thấp, nhưng cũng có thể dẫn đến hành vi khó hiểu hoặc không mong muốn trong một số trường hợp khác. Ví dụ: nếu trình duyệt tạm dừng một tác vụ cần thiết trong IndexedDB giao dịch, thì lệnh này có thể ảnh hưởng đến các thẻ đang mở khác trong cùng nguồn gốc, vì nhiều thẻ cùng lúc có thể truy cập cùng một cơ sở dữ liệu IndexedDB. Do đó, trình duyệt thường sẽ không tìm cách lưu các trang vào bộ nhớ đệm ở giữa 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 về mức độ ảnh hưởng của cách sử dụng API đối với điều kiện để thêm bộ nhớ đệm của trang, hãy xem bài viết Tối ưu hóa các trang của bạn cho bfcache.

bfcache và iframe

Nếu một trang chứa các iframe được nhúng thì bản thân các iframe đó không đủ điều kiện cho 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 chứ không phải 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 điều này. Bạn có thể áp dụng Chính sách về quyền được đặt trên khung chính hoặc việc sử dụng các thuộc tính sandbox để tránh tình trạng này.

bfcache và ứng dụng trang đơn (SPA)

Vì bfcache hoạt động với các điều hướng do trình duyệt quản lý, nên nó không hoạt động với "điều hướng 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ì phải khởi chạy lại hoàn toàn ứ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á do trình duyệt tự động thực hiện, nhưng nhà phát triển vẫn cần phải biết thời điểm xảy ra việc đó để có thể tối ưu hoá trang cũng như điều chỉnh mọi chỉ số hoặc phương pháp đo lường hiệu suất cho phù hợp.

Các sự kiện chính được dùng để quan sát bfcache là sự kiện chuyển đổi trang pageshowpagehide (được hỗ trợ bởi hầu hết các trình duyệt).

Các sự kiện mới hơn trong Vòng đời trangfreezeresume – 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 kích hoạt ngay sau sự kiện load khi trang đang tải lần đầu và bất cứ khi nào 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 các lượt tải trang thông thường với các lượt khôi phục trong 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 đã cố định. 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, nhưng nếu muốn đo tỷ lệ lượt truy cập vào 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 cho việc đo lường bfcache, hãy xem bài viết Cách bfcache ảnh hưởng đến số liệu phân tích và đo lường hiệu suất.

Quan sát khi một trang nhập bfcache

Sự kiện pagehide kích hoạt khi một trang bị 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 trạng thái là false, bạn có thể yên tâm rằng trang đó không có khả năng chuyển vào bộ nhớ đệm của trang web. 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 dự định lưu trang vào bộ nhớ đệm, nhưng có thể có những yếu tố khác khiến bạn không thể lưu trang 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 dự định lưu trang vào bộ nhớ đệm. Có thể bạn vẫn phải loại bỏ mã này vì một số lý do được giải thích sau.

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

Không phải tất cả các trang đều được lưu trong bfcache và ngay cả khi một trang được lưu trữ ở đó, nó sẽ không tồn tại vô thời hạn. Điều quan trọng là các 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) để dùng bfcache để tăng tối đa tỷ lệ lượt truy cập vào bộ nhớ đệm.

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

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

Cách quan trọng nhất để tối ưu hoá bfcache trong mọi trình duyệt là không bao giờ sử dụng sự kiện unload. Luôn luôn!

Sự kiện unload gây ra vấn đề cho các trình duyệt vì sự kiện này có trước bfcache và nhiều trang trên Internet hoạt động theo giả định (hợp lý) là một trang sẽ không tiếp tục tồn tại sau khi sự kiện unload kích hoạt. Đây là 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 phải đối mặt với một tình huống nan giải, họ phải lựa chọn giữa một điều có thể cải thiện trải nghiệm người dùng, nhưng cũng có thể có nguy cơ làm hỏng trang.

Trên máy tính, Chrome và Firefox đã chọn để các trang không đủ điều kiện dùng bộ nhớ đệm bfcache nếu thêm trình nghe unload. Phương pháp này ít rủi ro hơn nhưng cũng loại bỏ rất nhiều trang. 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 bị lỗi, Safari sẽ không chạy sự kiện unload khi người dùng đang di chuyển khỏi trang, khiến sự kiện trở nên 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ơ 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 để thêm bộ nhớ đệm, ngoại trừ trên iOS. Chrome yêu cầu tất cả trình duyệt đều sử dụng công cụ kết xuất WebKit, do đó, trình duyệt này hoạt động giống như Safari.

Thay vì dùng sự kiện unload, hãy 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 và cũng kích hoạt khi một trang được đưa vào bộ nhớ đệm bfcache.

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

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

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

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

Permission-Policy: unload=()

Điều này cũng ngăn các bên thứ ba hoặc tiện ích làm chậm tốc độ trang web bằng cách thêm các trình xử lý gỡ tải và làm cho 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 làm cho các trang của bạn không đủ điều kiện được thêm vào bfcache của trình duyệt hiện đại, nhưng trước đây có sự kiện này và nó vẫn không đáng tin cậy, vì vậy hãy tránh sử dụng nếu không thực sự cần thiết.

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

Hạn chế tối đa việc sử dụng Cache-Control: no-store

Cache-Control: no-store là một tiêu đề HTTP mà máy chủ web có thể đặt trên 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. URL này được sử 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à một bộ nhớ đệm HTTP, nhưng trước đây, khi Cache-Control: no-store được đặt 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 có nỗ lực để 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, bất kỳ trang nào sử dụng Cache-Control: no-store sẽ không đủ điều kiện dùng bộ nhớ đệm cho bộ nhớ đệm.

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

Đố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à các lệnh này không ảnh hưởng đến điều kiện dùng bộ nhớ đệm của trang web.

Xin lưu ý rằng khi đượ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 sẽ không được xem xét và sẽ không có trường hợp xác thực lại trước khi nội dung được hiển thị cho người dùng.

Đây vẫn có thể là một trải nghiệm người dùng tốt hơn, tuy nhiên, vì việc 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 sẽ không bị lỗi thời. Tuy nhiên, nếu nội dung của bạn thay đổi từng phút, thì bạn có thể tìm nạp mọi 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 nhạy cảm hoặc cũ sau khi khôi phục bfcache

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

Ví dụ: nếu người dùng chuyển đến một trang thanh toán rồi cập nhật giỏ hàng, thì thao tác điều hướng quay lại có thể để lộ 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à trường hợp người dùng đăng xuất khỏi một 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. Điều này có thể 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 tình huống như thế nà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
  }
});

Mặc dù tốt nhất là bạn nên cập nhật nội dung tại chỗ nhưng đối với một số thay đổi, bạn có thể muốn buộc tải lại toàn bộ. Các đoạn mã sau đây sẽ kiểm tra sự hiện diện của cookie của riêng từ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();
  }
});

Lợi thế của việc tải lại là sẽ vẫn bảo toàn được lịch sử (để cho phép điều hướng chuyển tiếp), nhưng chuyển hướng có thể thích hợp hơn trong một số trường hợp.

Khôi phục quảng cáo và bfcache

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 có tác động đến hiệu suất, một vấn đề đáng ngại là liệu hành vi như vậy có dẫn đến mức độ tương tác tốt hơn với quảng cáo hay không. Người dùng có thể đã nhận thấy một quảng cáo mà họ dự định quay lại để nhấp nhưng bằng cách tải lại thay vì khôi phục từ bfcache, họ không thể thực hiện được. 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 giả định.

Đối với những trang web muốn làm mới quảng cáo khi khôi phục bộ nhớ đệm, thì chỉ làm mới quảng cáo trên sự kiện pageshow khi event.persistedtrue cho phép việc 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à ví dụ về cách thực hiện việc này bằng Thẻ xuất bản của Google.

Tránh tham chiếu đến window.opener

Trong các trình duyệt cũ, nếu mở trang bằng window.open() từ 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 rủi ro bảo mật, bạn cũng không thể chuyển một trang có tệp tham chiếu window.opener khác rỗng vào bfcache, vì điều này có thể phá vỡ bất kỳ trang nào cố gắng truy cập nó.

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 hiện là chế độ mặc định trong tất cả trình duyệt hiện đại). Nếu trang web của bạn yêu cầu phải 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 đến đối tượng cửa sổ, thì cả cửa sổ đang mở và trình mở đều không đủ điều kiện để dùng bfcache.

Đóng các kết nối mở trước khi người dùng di chuyển ra khỏi

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

Nếu các tác vụ JavaScript đã lên lịch này chỉ truy cập API DOM (hoặc các API khác được tách riêng cho 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 mà cũng có thể truy cập được từ các trang khác có cùng nguồn gốc (ví dụ: IndexedDB, Web Locks, WebSockets), thì việc 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 trình quan sát 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 đây cho thấy cách đảm bảo rằng 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 rằng 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 kiểm tra các trang của mình để đả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 cố gắng điều hướng đi 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 đ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.

Nếu thử nghiệm 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 một trang trong Công cụ cho nhà phát triển từ bfcache
Đã khôi phục thành công một trang.

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à điều 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 điều đó là Có thể hành động.

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

Trong ví dụ này, việc sử dụng trình nghe sự kiện unload khiến trang không đủ điều kiện để lưu bfcache. Bạn có thể khắc phục vấn đề này bằng cách chuyển từ unload sang sử dụng 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, tính năng này thực hiện quy trình kiểm thử 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 một công cụ phân tích để đo lường lượt truy cập vào trang web của mình, bạn có thể nhận thấy tổng số lượt xem trang được báo cáo giảm xuống 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 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.

Để thêm các lượt khôi phục bfcache vào số lượt xem trang, hãy thiết lập trình nghe cho sự kiện pageshow và kiểm tra thuộc tính persisted.

Ví dụ sau cho thấy cách làm 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ệ lượt truy cập bfcache

Có thể bạn cũng muốn đ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. Bạn có thể thực hiện việc này bằng cách đo lường loại điều hướng cho 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ệ lượt truy cập bfcache bằng cách sử dụng số lượt điều hướng back_forward và điều hướng back_forward_cache.

Điều quan trọng cần nhận ra là có một số trường hợp, bên ngoài quyền kiểm soát của chủ sở hữu trang web, khi đ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ẻ và mở lại thẻ đó

Trong một số trường hợp như vậy, một số trình duyệt có thể giữ nguyên loại điều hướng ban đầu nên có thể hiển thị loại back_forward mặc dù những thao tác này không phải là thao tác đ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 để tiết kiệm bộ nhớ.

Vì vậy, chủ sở hữu trang web không nên mong đợi tỷ lệ lượt 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 ở tỷ lệ lớn thao tác tiến và lùi.

Nhóm Chrome đã thêm API NotRestoredReasons để giải thích lý do các trang không dùng bfcache, nhờ đó, nhà phát triển có thể cải thiện tỷ lệ truy cập vào bfcache. Nhóm Chrome cũng đã thêm các loại điều hướng vào CrUX, giúp họ có thể xem số lượng thao tác điều hướng trong bfcache mà không cần 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.

Do các thao tác điều hướng bfcache khôi phục một trang hiện có thay vì bắt đầu một lượt tải trang mới, tổng số lần tải trang được thu thập sẽ giảm khi bfcache được bật. Tuy nhiên, điều quan trọng là việc tải trang được thay thế bằng việc khôi phục bfcache có thể là một trong những lượt tải trang nhanh nhất trong tập dữ liệu của bạn. Điều này là do điều hướng tiến và lùi, theo định nghĩa, là các 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 tiên (do lưu vào bộ nhớ đệm HTTP, như đã đề cập trước đó).

Kết quả là giảm tốc độ tải trang trong tập dữ liệu, dẫn đến khả năng làm lệch tốc độ phân phối chậm hơn, mặc dù trên thực tế, hiệu suất mà người dùng trải nghiệm có thể đã cải thiện!

Có một vài cách để giải quyết 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. Điều này cho phép bạn tiếp tục theo dõi hiệu suất của mình 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 âm. 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 đến byte đầu tiên (TTFB).

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

Tác động đối với Chỉ số quan trọng chính của 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 theo nhiều phương diện (tốc độ tải, tính tương tác, độ ổn định về hình ảnh). Ngoài ra, do người dùng trải nghiệm việc khôi phục trong bfcache khi điều hướng nhanh hơn so với khi tải toàn bộ trang, nên các chỉ số quan trọng về trang web sẽ phản ánh điều này. Xét cho cùng, người dùng không quan tâm liệu bfcache đã được bật hay chưa, họ chỉ quan tâm rằng quá trình điều hướng thật nhanh!

Các công cụ thu thập và báo cáo về chỉ số Core Web Vitals (chẳng hạn như Báo cáo trải nghiệm người dùng trên Chrome) coi việc khôi phục bfcache là những lượt truy cập trang riêng biệt trong tập dữ liệu của chúng. Ngoài ra, mặc dù không có API hiệu suất web chuyên dụng để đo lường các chỉ số này sau khi khôi phục bfcache, nhưng bạn có thể ước chừng 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ề mức độ ảnh hưởng của bfcache đối với 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 JS web-quan trọng.

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

Tài nguyên khác