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 Tiện ích đã đượ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. Xem bên dưới để biết chi tiết.

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

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

Trước khi ra mắt tính năng 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ẻ chỉ có một trang đang hoạt động. Đây luôn là nút hiển thị. Nếu người dùng quay lại trang trước, trang đang hoạt động sẽ bị huỷ (Trang B) và trang trước đó trong nhật ký 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ề phần nào của vòng đời trang vì chỉ có một phần cho một thẻ, trạng thái đang hoạt động/hiển thị.

Loại bỏ trang đang hoạt động
Loại bỏ trang đang hoạt động.

Với tính năng Bộ nhớ đệm cho thao tác tiến/lùi và tính năng kết xuất trước, mối quan hệ một với một giữa các thẻ và trang không còn tồn tại 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 dưới dạng trang hiển thị trước (không hiển thị), chuyển đổi thành 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 Quay lại/Tiến (không hiển thị) khi người dùng chuyển đến một trang khác, tất cả đều không làm cho trang bị huỷ. Ở 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 được hiển thị để giúp các tiện ích hiểu được trạng thái của các trang.

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 của thao tác Quay lại/Tiến.

Nhà phát triển tiện ích sẽ thấy thay đổi gì?

FrameId == 0

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

Các tác giả tiện ích giả định frameId của khung ngoài cùng là 0 (một 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 cho một thẻ là không chính xác. frameId == 0 sẽ vẫn 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 trang khác trong cùng một thẻ sẽ khác 0. Thêm trường mới frameType để khắc phục vấn đề này. Hãy xem phần "Làm cách nào để xác định xem một khung hình có phải là khung hình ngoài cùng khô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 các 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 có thể thay đổi (ví dụ: bằng cách điều hướng) nhưng frameId sẽ không thay đổi, vì vậy, bạn khó có thể liên kết một sự kiện đã xảy ra trong một tài liệu cụ thể với chỉ frameIds. Chúng tôi sẽ giới thiệu khái niệm về documentId. Đây là giá trị nhận dạng duy nhấ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, thì giá trị nhận dạng sẽ thay đổi. Trường này hữu ích để xác định thời điểm các trang thay đổi trạng thái vòng đời (giữa chế độ kết xuất trước/đang hoạt động/đã lưu vào bộ nhớ đệm) vì trường này vẫn giữ nguyên.

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 ở vòng đời nào?""Làm cách nào để xác định thời điểm chuyển đổi trang?".

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

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

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

  • "prerender" : Hiện không hiển thị cho người dùng nhưng có thể đang chuẩn bị hiển thị cho người dùng.
  • "active": Hiện đang 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 xem một khung là khung ngoài cùng hay không?

Trước đây, các tiện ích có thể đã kiểm tra xem frameId == 0 có xác định được sự kiện xảy ra cho khung ngoài cùng hay không. Với nhiều trang trong một thẻ, giờ đây chúng ta có nhiều khung hình ngoài cùng, vì vậy, định nghĩa của frameId sẽ gặp vấn đề. Bạn sẽ không bao giờ nhận được sự kiện về khung Đẩy lui/Tiến được lưu vào bộ nhớ đệm. Tuy nhiên, đối với các khung được kết xuất trước, frameId sẽ không bằng 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 đó có phải là khung ngoài cùng hay không là 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 liệu khung đó 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. Xin lưu ý rằng có nhiều bộ lọc như vậy. Ví dụ: nếu bạn có các trang được kết xuất trước và lưu vào bộ nhớ đệm, thì mỗi trang sẽ có một khung ngoài cùng có thể được gọi là khung trên cùng.
  • "fenced_frame": Dành để sử dụng trong tương lai.
  • "sub_frame": Thường là một 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ụ: tab.documentLifecycle === “active” && frameType === “outermost_frame”

Làm cách nào để giải quyết vấn đề về thời gian sử dụng với khung?

Như đã nói ở trên, một khung lưu trữ một 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 gây 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, URL đó có thể khác với thời điểm xảy ra sự kiện. Đâ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 không bắt buộc phải có frameId nếu bạn 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 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 xem các sự kiện WebNavigation.

Đối với thao tác điều hướng đầu tiên trên bất kỳ trang nào, bạn sẽ thấy 4 sự kiện theo thứ tự được liệt kê bên dưới. Xin 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 lui/tiến 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 (nhưng DocumentLifecyle"active").

onBeforeNavigate
onCommitted
onCompleted

documentId sẽ giữ nguyên như trong các sự kiện ban đầu. Điều này được minh hoạ ở trên khi documentId == xyz kích hoạt. 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 đặt câu hỏi trên nhóm chromium-extensions.