Ekstensi Chrome: Memperluas API untuk mendukung Navigasi Instan

Dave Tapuska
Dave Tapuska

TL;DR: Extensions API telah diupdate untuk mendukung back/forward cache, yang melakukan pramuat navigasi. Lihat detailnya di bawah ini.

Chrome telah bekerja keras untuk membuat navigasi menjadi cepat. Teknologi Navigasi Instan seperti Back/Forward Cache (shipped di desktop di Chrome 96) dan Speculation Rules (shipped di Chrome 103) meningkatkan pengalaman kembali dan maju. Dalam postingan ini, kami akan membahas update yang telah kami lakukan pada API ekstensi browser untuk mengakomodasi alur kerja baru ini.

Memahami jenis-jenis halaman

Sebelum diperkenalkannya Back/Forward Cache dan pra-rendering, setiap tab hanya memiliki satu halaman aktif. Inilah yang selalu terlihat. Jika pengguna kembali ke halaman sebelumnya, halaman aktif akan dihancurkan (Halaman B) dan halaman sebelumnya dalam histori akan dibuat kembali sepenuhnya (Halaman A). Ekstensi tidak perlu mengkhawatirkan bagian mana dari halaman siklus proses karena hanya ada satu untuk sebuah tab, yaitu status aktif/terlihat.

Penghapusan halaman aktif
Penghapusan halaman aktif.

Dengan Back/Forward Cache dan pra-rendering, tidak ada lagi hubungan one-to-one antara tab dan halaman. Sekarang, setiap tab sebenarnya menyimpan beberapa transisi halaman dan halaman antarstatus, bukan dihancurkan dan direkonstruksi.

Misalnya, sebuah halaman dapat memulai prosesnya sebagai halaman pra-rendering (tidak terlihat), beralih ke halaman aktif (terlihat) saat pengguna mengklik link, lalu disimpan dalam Back/Forward Cache (tidak terlihat) saat pengguna membuka halaman lain, semuanya tanpa pernah dihancurkan. Nanti dalam artikel ini, kita akan melihat properti baru yang diekspos untuk membantu ekstensi memahami halaman status yang ada.

Jenis halaman
Jenis halaman.

Perhatikan bahwa tab dapat memiliki serangkaian halaman pra-render (bukan hanya satu), satu halaman yang aktif (terlihat), dan serangkaian halaman yang di-cache Mundur/Teruskan.

Apa saja yang berubah bagi developer ekstensi?

IdBingkai == 0

Di Chromium, kami menyebut frame paling atas/utama sebagai frame terluar.

Penulis ekstensi yang mengasumsikan frameId pada frame terluar adalah 0 (praktik terbaik sebelumnya) mungkin mengalami masalah. Karena sekarang tab dapat memiliki beberapa frame terluar (halaman yang telah di-pra-render dan yang di-cache), asumsi bahwa ada satu frame terluar untuk sebuah tab salah. frameId == 0 akan tetap mewakili frame terluar halaman aktif, tetapi frame terluar dari halaman lain di tab yang sama akan menjadi bukan nol. Kolom baru frameType telah ditambahkan untuk memperbaiki masalah ini. Lihat bagian “Bagaimana cara menentukan apakah suatu frame merupakan frame terluar?” dalam postingan ini.

Siklus proses frame versus dokumen

Konsep lain yang bermasalah dengan ekstensi adalah siklus proses frame. Frame menghosting dokumen (yang terkait dengan URL yang di-commit). Dokumen dapat berubah (misalnya dengan menavigasi), tetapi frameId tidak, sehingga sulit untuk mengaitkan sesuatu terjadi dalam dokumen tertentu hanya dengan frameIds. Kami memperkenalkan konsep documentId yang merupakan ID unik untuk setiap dokumen. Jika sebuah {i>frame<i} dinavigasi dan membuka dokumen baru, {i>identifier<i} akan berubah. Kolom ini berguna untuk menentukan kapan halaman mengubah status siklus prosesnya (antara pra-rendering/aktif/di-cache) karena status tetap sama.

Peristiwa navigasi web

Peristiwa di namespace chrome.webNavigation dapat diaktifkan beberapa kali di halaman yang sama, bergantung pada siklus prosesnya. Lihat bagian “Bagaimana cara mengetahui siklus proses apa yang ada di halaman?” dan “Bagaimana cara menentukan waktu transisi halaman?”.

Bagaimana cara mengetahui siklus proses apa yang ada di halaman?

Jenis DocumentLifecycle telah ditambahkan ke sejumlah API ekstensi tempat frameId sebelumnya tersedia. Jika jenis DocumentLifecycle ada pada peristiwa (seperti onCommitted), nilainya adalah status saat peristiwa dihasilkan. Anda selalu dapat membuat kueri informasi dari metode WebNavigation getFrame() dan getAllFrames(), tetapi sebaiknya gunakan nilai dari peristiwa. Jika Anda menggunakan salah satu metode tersebut, Anda dapat mengetahui status frame dapat berubah antara saat peristiwa dibuat dan saat promise yang ditampilkan oleh kedua metode tersebut di-resolve.

DocumentLifecycle memiliki nilai berikut:

  • "prerender" : Saat ini tidak ditampilkan kepada pengguna, tetapi bersiap untuk ditampilkan kepada pengguna.
  • "active": Ditampilkan kepada pengguna.
  • "cached": Disimpan dalam Back/Forward Cache.
  • "pending_deletion": Dokumen sedang dihancurkan.

Bagaimana cara menentukan apakah {i>frame<i} adalah {i>frame<i} terluar?

Sebelumnya, ekstensi mungkin telah memeriksa apakah frameId == 0 untuk menentukan apakah peristiwa yang terjadi adalah untuk frame terluar atau tidak. Dengan beberapa halaman dalam tab, kami sekarang memiliki beberapa frame terluar, sehingga definisi frameId bermasalah. Anda tidak akan pernah menerima peristiwa tentang frame yang di-cache Back/Forward. Namun, untuk frame yang dipra-render, frameId akan menjadi bukan nol untuk frame terluar. Jadi, penggunaan frameId == 0 sebagai sinyal untuk menentukan apakah frame terluar salah.

Untuk membantu melakukan hal ini, kami memperkenalkan jenis baru yang disebut FrameType, sehingga menentukan apakah frame merupakan frame terluar kini menjadi mudah. FrameType memiliki nilai berikut:

  • "outermost_frame": Biasanya disebut sebagai bingkai paling atas. Perhatikan bahwa ini ada lebih dari satu. Misalnya, jika Anda memiliki halaman yang di-pra-render dan di-cache, masing-masing memiliki frame terluar yang dapat disebut frame paling atas.
  • "fenced_frame": Dicadangkan untuk penggunaan pada masa mendatang.
  • "sub_frame": Biasanya iframe.

Kita dapat menggabungkan DocumentLifecycle dengan FrameType dan menentukan apakah suatu frame adalah frame terluar yang aktif. Contoh: js tab.documentLifecycle == “active” && frameType == “outermost_frame”

Bagaimana cara mengatasi masalah waktu penggunaan dengan frame?

Seperti yang telah kami sampaikan di atas, frame menghosting dokumen dan frame dapat membuka dokumen baru, tetapi frameId tidak akan berubah. Hal ini akan menimbulkan masalah jika Anda menerima peristiwa hanya dengan frameId. Jika Anda mencari URL frame itu mungkin berbeda dengan saat peristiwa terjadi, hal ini disebut masalah waktu penggunaan.

Untuk mengatasinya, kami memperkenalkan documentId (dan parentDocumentId). Metode webNavigation.getFrame() kini menjadikan frameId opsional jika documentId disediakan. documentId akan berubah setiap kali frame dibuka.

Bagaimana cara menentukan kapan halaman bertransisi?

Ada sinyal eksplisit untuk menentukan kapan transisi halaman antarstatus.

Mari kita lihat peristiwa WebNavigation.

Untuk navigasi pertama di halaman mana pun, Anda akan melihat empat peristiwa sesuai urutan yang tercantum di bawah. Perhatikan bahwa keempat peristiwa ini dapat terjadi dengan status DocumentLifecycle berupa "prerender" atau "active".

onBeforeNavigate
onCommitted
onDOMContentLoaded
onCompleted

Hal ini diilustrasikan dalam diagram di bawah yang menunjukkan perubahan documentId menjadi "xyz" saat halaman pra-rendering menjadi halaman aktif.

DocumentId berubah saat halaman pra-rendering menjadi halaman aktif
documentId akan berubah saat halaman pra-rendering menjadi halaman aktif.

Saat halaman bertransisi dari Back/Forward Cache atau pra-render ke status aktif, akan ada tiga peristiwa lagi (tetapi dengan DocumentLifecyle menjadi "active").

onBeforeNavigate
onCommitted
onCompleted

documentId akan tetap sama seperti pada peristiwa asli. Hal ini diilustrasikan di atas saat documentId == xyz diaktifkan. Perhatikan bahwa peristiwa navigasi yang sama akan diaktifkan, kecuali untuk peristiwa onDOMContentLoaded karena halaman sudah dimuat.

Jika ada komentar atau pertanyaan, jangan ragu untuk bertanya di grup chromium-extensions.