Tiện ích của Chrome: Mở rộng API để hỗ trợ Điều hướng tức thì

Dave Tapuska
Dave Tapuska

Tóm tắt: API Extensions đã được cập nhật để hỗ trợ bộ nhớ đệm cho thao tác tiến/lùi, tải trước các thao tác điều hướng. Vui lòng xem chi tiết bên dưới.

Chrome đang nỗ lực để giúp điều hướng trở nên nhanh chóng. Các công nghệ Điều hướng tức thì như Bộ nhớ đệm cho thao tác tiến/lùi (đã xuất hàng trên máy tính trong Chrome 96) và Quy tắc suy đoán (đã xuất hàng trong Chrome 103) giúp cải thiện cả trải nghiệm sử dụng lẫn sau này. Trong bài đăng này, chúng ta sẽ khám phá các điểm cập nhật mà chúng tôi đã thực hiện đối với các API tiện ích trình duyệt để phù hợp với các quy trình công việc mới này.

Tìm hiểu các loại trang

Trước khi ra mắt Bộ nhớ đệm cho thao tác tiến/lùi và tính năng kết xuất trước, mỗi thẻ riêng lẻ chỉ có một trang đang hoạt động. Đây luôn là mục người dùng nhìn thấy. Nếu người dùng quay lại trang trước, thì trang đang hoạt động sẽ bị huỷ bỏ (Trang B) và trang trước đó trong lịch sử sẽ được tạo lại hoàn toàn (Trang A). Các tiện ích không cần lo lắng về việc các trang trong vòng đời chứa phần nào vì mỗi thẻ chỉ có một phần, đó là trạng thái đang hoạt động/hiển thị.

Xoá trang đang hoạt động
Xoá trang đang hoạt động.

Với bộ nhớ đệm cho thao tác tiến/lùi và kết xuất trước, không còn mối quan hệ một với một giữa các thẻ và trang nữa. Giờ đây, mỗi thẻ thực sự lưu trữ nhiều trang và các trang chuyển đổi giữa các trạng thái thay vì bị huỷ và tạo lại.

Ví dụ: một trang có thể bắt đầu hoạt động dưới dạng một trang được kết xuất trước (không hiển thị), chuyển đổi sang một trang đang hoạt động (hiển thị) khi người dùng nhấp vào một đường liên kết, sau đó được lưu trữ trong Bộ nhớ đệm cho thao tác tiến/lùi (không hiển thị) khi người dùng chuyển đến một trang khác mà không phải huỷ trang đó. Ở phần sau của bài viết này, chúng ta sẽ xem xét các thuộc tính mới hiển thị để giúp các tiện ích hiểu được trang trạng thái là gì.

Các loại trang
Các loại trang.

Xin lưu ý rằng một thẻ có thể có một loạt các trang được kết xuất trước (không chỉ một trang), một trang đang hoạt động (hiển thị) và một loạt các trang được lưu vào bộ nhớ đệm cho tính năng Quay lại/Chuyển tiếp.

Có gì thay đổi đối với các nhà phát triển tiện ích?

Mã khung hình == 0

Trong Chromium, chúng tôi gọi khung trên cùng/chính là khung ngoài cùng.

Tác giả tiện ích giả định frameId của khung ngoài cùng là 0 (phương pháp hay nhất trước đây) có thể gặp vấn đề. Vì một thẻ hiện có thể có nhiều khung ngoài cùng (các trang được kết xuất trước và lưu vào bộ nhớ đệm) nên giả định rằng có một khung ngoài cùng duy nhất cho một thẻ là không chính xác. frameId == 0 vẫn sẽ tiếp tục biểu thị khung ngoài cùng của trang đang hoạt động, nhưng các khung ngoài cùng của các trang khác trong cùng một thẻ sẽ khác 0. Một trường mới frameType đã được thêm vào để khắc phục vấn đề này. Hãy xem phần "Làm cách nào để xác định một khung hình có phải là khung ngoài cùng?" trong bài đăng này.

Vòng đời của khung so với tài liệu

Một khái niệm khác gây ra vấn đề với tiện ích là vòng đời của khung. Khung lưu trữ một tài liệu (được liên kết với một URL đã cam kết). Tài liệu này có thể thay đổi (giả sử bằng cách điều hướng) nhưng frameId thì không, vì vậy, khó liên kết rằng một điều gì đó đã xảy ra trong một tài liệu cụ thể chỉ bằng frameIds. Chúng tôi sẽ ra mắt khái niệm documentId, là giá trị nhận dạng riêng biệt cho mỗi tài liệu. Nếu một khung được điều hướng và mở một tài liệu mới, giá trị nhận dạng sẽ thay đổi. Trường này rất hữu ích khi xác định thời điểm các trang thay đổi trạng thái vòng đời (giữa quá trình kết xuất trước/đang hoạt động/lưu vào bộ nhớ đệm) vì trường này không thay đổi.

Sự kiện điều hướng trên web

Các sự kiện trong không gian tên chrome.webNavigation có thể kích hoạt nhiều lần trên cùng một trang, tuỳ thuộc vào vòng đời của sự kiện đó. Xem các phần "Làm cách nào để biết trang đang ở trong vòng đời nào?""Làm cách nào để xác định thời điểm một trang chuyển đổi?".

Làm cách nào để biết trang này đang ở trong vòng đời nào?

Loại DocumentLifecycle đã được thêm vào một số API tiện ích mà frameId đã có trước đây. Nếu loại DocumentLifecycle xuất hiện trong một sự kiện (chẳng hạn như onCommitted), thì giá trị của loại này là trạng thái mà sự kiện được tạo. Bạn luôn có thể truy vấn thông tin từ phương thức WebNavigation getFrame()getAllFrames(), nhưng việc sử dụng giá trị từ sự kiện luôn được ưu tiên. Nếu bạn sử dụng một trong hai phương thức, hãy lưu ý rằng trạng thái của khung hình có thể thay đổi giữa thời điểm sự kiện được tạo và thời điểm các lời hứa trả về bằng cả hai phương thức được giải quyết.

DocumentLifecycle có các giá trị sau:

  • "prerender" : Hiện không được hiển thị cho người dùng nhưng đang chuẩn bị để có thể hiển thị cho người dùng.
  • "active": Hiển thị cho người dùng.
  • "cached": Được lưu trữ trong bộ nhớ đệm cho thao tác tiến/lùi.
  • "pending_deletion": Tài liệu đang bị huỷ.

Làm cách nào để xác định một khung hình có phải là khung ngoài cùng không?

Các tiện ích trước đây có thể đã kiểm tra xem frameId == 0 để xác định xem sự kiện xảy ra có phải là dành cho khung ngoài cùng hay không. Với nhiều trang trong một thẻ, chúng tôi hiện có nhiều khung ngoài cùng, vì vậy, việc định nghĩa frameId có vấn đề. Bạn sẽ không bao giờ nhận được các sự kiện liên quan đến khung được lưu vào bộ nhớ đệm cho thao tác tiến/lùi. Tuy nhiên, đối với các khung được kết xuất trước, frameId sẽ khác 0 đối với khung ngoài cùng. Vì vậy, việc sử dụng frameId == 0 làm tín hiệu để xác định xem đây có phải là khung ngoài cùng không chính xác.

Để giúp giải quyết vấn đề này, chúng tôi đã giới thiệu một loại mới có tên là FrameType để dễ dàng xác định xem khung hình có thực sự là khung ngoài cùng hay không. FrameType có các giá trị sau:

  • "outermost_frame": Thường được gọi là khung trên cùng. Lưu ý rằng có nhiều trường hợp trong số này. Ví dụ: nếu bạn có một trang được kết xuất trước và lưu vào bộ nhớ đệm, mỗi trang có một khung ngoài cùng có thể được gọi là khung trên cùng.
  • "fenced_frame": Được dành riêng để sử dụng trong tương lai.
  • "sub_frame": Thường là iframe.

Chúng ta có thể kết hợp DocumentLifecycle với FrameType và xác định xem một khung có phải là khung ngoài cùng đang hoạt động hay không. Ví dụ: js tab.documentLifecycle == “active” && frameType == “outermost_frame”

Làm thế nào để khắc phục vấn đề về thời gian sử dụng liên quan đến khung hình?

Như đã đề cập ở trên, khung lưu trữ tài liệu và khung đó có thể điều hướng đến một tài liệu mới nhưng frameId sẽ không thay đổi. Điều này sẽ tạo ra sự cố khi bạn nhận được một sự kiện chỉ có frameId. Nếu bạn tra cứu URL của khung, thì URL này có thể khác với thời điểm sự kiện xảy ra, đây được gọi là vấn đề về thời gian sử dụng.

Để giải quyết vấn đề này, chúng tôi đã giới thiệu documentId (và parentDocumentId). Phương thức webNavigation.getFrame() hiện khiến frameId không bắt buộc nếu cung cấp documentId. documentId sẽ thay đổi bất cứ khi nào một khung được điều hướng.

Làm cách nào để xác định thời điểm chuyển đổi một trang?

Có các tín hiệu rõ ràng để xác định thời điểm một trang chuyển đổi giữa các trạng thái.

Hãy cùng xem các sự kiện WebNavigation.

Trong lần điều hướng đầu tiên trên một trang bất kỳ, bạn sẽ thấy bốn sự kiện theo thứ tự được liệt kê dưới đây. Lưu ý rằng 4 sự kiện này có thể xảy ra với trạng thái DocumentLifecycle"prerender" hoặc "active".

onBeforeNavigate
onCommitted
onDOMContentLoaded
onCompleted

Điều này được minh hoạ trong sơ đồ dưới đây, cho thấy documentId thay đổi thành "xyz" khi trang được kết xuất trước trở thành trang đang hoạt động.

documentId thay đổi khi trang được kết xuất trước trở thành trang đang hoạt động
documentId thay đổi khi trang được kết xuất trước trở thành trang đang hoạt động.

Khi một trang chuyển đổi từ Bộ nhớ đệm cho thao tác tiến/lùi hoặc kết xuất trước sang trạng thái đang hoạt động, sẽ có thêm 3 sự kiện khác (nhưng với DocumentLifecyle"active").

onBeforeNavigate
onCommitted
onCompleted

documentId sẽ giữ nguyên như trong các sự kiện gốc. Điều này được minh hoạ ở trên khi documentId == xyz kích hoạt. Xin lưu ý rằng các sự kiện điều hướng tương tự sẽ kích hoạt, ngoại trừ sự kiện onDOMContentLoaded vì trang đã được tải.

Nếu bạn có nhận xét hoặc câu hỏi, vui lòng hỏi trên nhóm chromium-extensions.