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 thành phần điều hướng. Vui lòng xem chi tiết bên dưới.

Chrome đang nỗ lực làm cho việc đ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 (đã vận chuyển trên máy tính trong Chrome 96) và Quy tắc suy đoán (đã xuất bản trong Chrome 103) giúp cải thiện cả trải nghiệm quay lại và tua lại. Trong bài đăng này, chúng ta sẽ khám phá những 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 những quy trình làm việc mới này.

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

Trước khi có bộ nhớ đệm cho thao tác tiến/lùi và kết xuất trước, mỗi thẻ riêng lẻ chỉ có một trang hoạt động. Đây luôn là ảnh được 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 các trang vòng đời vì chỉ có một thẻ cho một thẻ, đó 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à tính năng kết xuất trước, các thẻ và trang không còn mối liên hệ một với một nữa. Giờ đây, mỗi thẻ thực ra lưu trữ nhiều trang và 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 trang được kết xuất trước (không hiển thị), chuyển đổi sang trang đang hoạt động (hiển thị) khi người dùng nhấp vào một đường liên kết và 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 hề huỷ bỏ trang đó. Trong 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 tiện ích nắm được trạng thái của 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 trang đã lưu vào bộ nhớ đệm cho thao tác tiến/lùi.

Có gì thay đổi đối với 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/khung 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 đó) có thể gặp vấn đề. Vì hiện tại, thẻ có thể có nhiều khung hình ngoài cùng (các trang được kết xuất trước và lưu vào bộ nhớ đệm) nên việc cho rằng chỉ có một khung hình 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 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 frameType mới đã đượ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 xem một khung hình có phải là khung ngoài cùng hay không?” trong bài đăng này.

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

Một khái niệm khác có thể gặp vấn đề với tiện ích là vòng đời của khung. Một khung lưu trữ 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 (chẳng hạn như bằng cách điều hướng) nhưng frameId thì không, và vì vậy, khó có thể liên kết rằng điều gì đó đã xảy ra trong một tài liệu cụ thể chỉ với frameIds. Chúng tôi sẽ giới thiệu một 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, giá trị nhận dạng sẽ thay đổi. Trường này giúp ích cho việc xác định thời điểm các trang thay đổi trạng thái vòng đời (giữa các lượt kết xuất trước/đang hoạt động/đã lưu vào bộ nhớ đệm) vì các trang này không thay đổi.

Sự kiện di chuyển 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 đó. Hãy xem 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 một trang chuyển đổi?".

Làm thế nào để biết trang đang ở 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 đó. 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 đó sẽ 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ừ các phương thức WebNavigation getFrame()getAllFrames(), nhưng việc sử dụng giá trị từ sự kiện sẽ 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 cho đến thời điểm giải quyết những lời hứa trả về mà cả hai phương thức trả về.

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

  • "prerender" : Hiện chưa được hiển thị cho người dùng nhưng đang chuẩn bị để có thể hiển thị với người dùng.
  • "active": Hiện hiển thị với 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 hình có phải 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 để xác định xem sự kiện đang xảy ra có 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 nên việc định nghĩa frameId rất khó. Bạn sẽ không bao giờ nhận được sự kiện về một 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 đó có phải là khung ngoài cùng là không chính xác hay không.

Để giúp giải quyết vấn đề này, chúng tôi đã ra mắt một loại mới có tên là FrameType. Nhờ vậy, việc xác định xem khung hình có thực sự là khung ngoài cùng hay không đã trở nên dễ dà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ó thể có bội số của các biểu thức nà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 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 để 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 cách nào để khắc phục vấn đề về thời gian sử dụng với khung hình?

Như chúng tôi đã 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 sẽ gây ra sự cố khi bạn nhận được một sự kiện chỉ kèm theo một frameId. Nếu bạn tra cứu URL của khung hình, URL này có thể khác với khi sự kiện xảy ra, thì đâ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 ra mắt documentId (và parentDocumentId). Phương thức webNavigation.getFrame() hiện đặt frameId là không bắt buộc nếu có 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 một trang chuyển đổi?

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 của WebNavigation.

Trong lần điều hướng đầu tiên của một trang bất kỳ, bạn sẽ thấy 4 sự kiện theo thứ tự như liệt kê dưới đây. 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 cho thao tác tiến/lùi hoặc kết xuất trước sang trạng thái hoạt động, sẽ có thêm 3 sự kiện nữa (nhưng với DocumentLifecyle"active").

onBeforeNavigate
onCommitted
onCompleted

documentId sẽ vẫn 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. Xin lưu ý rằng cùng một sự kiện điều hướng 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 nào, vui lòng hỏi trên nhóm chromium-extensions.