Rumah > Soal Jawab > teks badan
P粉0345716232023-08-25 17:51:37
Tidak seperti chrome.webRequest API, chrome.webNavigation API berfungsi dengan sempurna kerana chrome.webNavigation API boleh bangun Service Worker, kini anda boleh cuba memasukkan chrome.webRequest API chrome.webRequest dalam API chrome.webRequest webNavigation.
chrome.webNavigation.onBeforeNavigate.addListener(function(){ chrome.webRequest.onResponseStarted.addListener(function(details){ //............. //............. },{urls: ["*://domain/*"],types: ["main_frame"]}); },{ url: [{hostContains:"domain"}] });
P粉3863180862023-08-25 00:41:03
Penerangan masalah
Penyelesaian:
• Eksploitasi
• 离屏
API
• nativeMessaging
API
• WebSocket
API
• chrome
API Pemesejan
• Tab khusus
Perhatian
Secara takrifan, Pekerja Perkhidmatan (SW) tidak boleh diteruskan dan penyemak imbas mesti menamatkan semua aktiviti/permintaannya secara paksa selepas masa tertentu, iaitu 5 minit dalam Chrome. Pemasa tidak aktif (iaitu apabila tiada aktiviti sedemikian berlaku) adalah lebih pendek: 30 saat.
Pasukan Chromium pada masa ini menganggap gelagat ini sebagai baik (pasukan kadang-kadang melonggarkan beberapa aspek, cth. Chrome 114 memanjangkan port chrome.runtime selepas setiap mesej), tetapi ini hanya terpakai pada sambungan yang memerhatikan peristiwa yang jarang berlaku, Acara ini adalah hanya berjalan beberapa kali sehari, sekali gus mengurangkan jejak memori penyemak imbas antara larian (cth. webRequest/webNavigation acara dengan url > penapisan untuk tapak yang jarang dilawati). Sambungan ini boleh direka bentuk semula untuk mengekalkan keadaan, Contoh. Malangnya, idyll seperti itu tidak dapat dikekalkan dalam banyak kes.
Isu 1: Chrome 106 dan lebih awal tidak membangunkan perisian untuk acara webRequest. p>
Walaupun anda boleh cuba melanggan API seperti chrome.webNavigation
seperti yang ditunjukkan dalam jawapan lain, ia hanya membantu untuk acara yang berlaku selepas urutan pekerja dimulakan.
Masalah 2: Kakitangan secara rawak berhenti bangun kerana peristiwa.
Penyelesaianmungkin dengan memanggil chrome.runtime.reload().
Isu 3: Chrome 109 dan lebih awal tidak boleh melanjutkan kitaran hayat perisian acara API chrome
baharu daripada skrip latar belakang yang sudah dijalankan. Ini bermakna kod anda tidak akan dapat menjalankan apa-apa secara tidak segerak dengan pasti apabila peristiwa berlaku dalam beberapa milisaat terakhir daripada tamat masa tidak aktif selama 30 saat. Ini bermakna pengguna akan menganggap sambungan anda tidak boleh dipercayai.
Soalan 4: Prestasi akan lebih teruk daripada MV2 jika sambungan mengekalkan sambungan jauh atau keadaan (pembolehubah) mengambil masa yang lama untuk dibina semula, atau jika anda memerhatikan kejadian yang kerap seperti berikut:
Melancarkan SW untuk acara baharu pada asasnya seperti membuka tab baharu. Ia mengambil masa kira-kira 50 ms untuk mencipta persekitaran, mungkin 100 ms (atau 1000 ms, bergantung pada jumlah kod) untuk menjalankan keseluruhan skrip SW, dan mungkin 1 ms (atau 1000 ms, bergantung pada data) untuk membaca nyatakan daripada simpanan dan bina semula/hidratkannya) . Walaupun dengan skrip yang hampir kosong, ia mengambil masa sekurang-kurangnya 50 milisaat, yang merupakan overhed yang agak banyak untuk memanggil pendengar acara, yang hanya mengambil masa 1 milisaat.
SW mungkin dimulakan semula ratusan kali sehari kerana peristiwa sedemikian dijana sebagai tindak balas kepada tindakan pengguna dengan jurang semula jadi, seperti mengklik tab dan kemudian menulis sesuatu, semasa perisian ditamatkan dan Acara baharu dimulakan semula, menggunakan CPU, cakera , bateri dan secara amnya memperkenalkan ketinggalan yang boleh dilihat dalam tindak balas penskalaan yang kerap.
Chrome 110 memperkenalkan pepijat: memanggil sebarang asynchronous chrome
API akan menyebabkan urutan pekerja berjalan selama 30 saat tambahan. Pepijat ini belum dibetulkan lagi.
//background.js
const keepAlive = () => setInterval(chrome.runtime.getPlatformInfo, 20e3);
chrome.runtime.onStartup.addListener(keepAlive);
keepAlive();
Disumbangkan oleh Kevin Augusto.
Dalam Chrome 109 dan ke atas, anda boleh menggunakan API luar skrin untuk membuat dokumen luar skrin dan menghantar beberapa mesej daripadanya setiap 30 saat atau kurang untuk memastikan Pekerja Perkhidmatan berjalan. Pada masa ini, hayat dokumen tidak terhad (hanya main balik audio dihadkan, yang kami tidak gunakan), tetapi ini mungkin berubah pada masa hadapan.
manifest.json
"permissions": ["offscreen"]
luar skrin.html
<script src="offscreen.js"></script>
luar skrin.js
setInterval(async () => {
(await navigator.serviceWorker.ready).active.postMessage('keepAlive');
}, 20e3);
background.js
async function createOffscreen() {
await chrome.offscreen.createDocument({
url: 'offscreen.html',
reasons: ['BLOBS'],
justification: 'keep service worker running',
}).catch(() => {});
}
chrome.runtime.onStartup.addListener(createOffscreen);
self.onmessage = e => {}; // keepAlive
createOffscreen();
nativeMessaging
Urutan pekerja perkhidmatan "berterusan" hos Dalam Chrome 105 dan ke atas, lalukan sahaja chrome.runtime.connectNative. Jika proses hos ditamatkan kerana ranap atau tindakan pengguna, port akan ditutup dan perisian akan ditamatkan seperti biasa. Anda boleh menghalangnya daripada memanggil chrome.runtime.connectNative sekali lagi dengan mendengar acara onDisconnect port.
Chrome 116 dan ke atas: Bertukar mesej WebSocket setiap 30 saat untuk memastikan ia terus hidup, cth.
Keburukan:
或 *://*/*
), yang akan meletakkan kebanyakan sambungan ke dalam baris gilir semakan perlahan kedai dalam talian Amaran! Jika anda mempunyai port yang disambungkan, jangan gunakan penyelesaian ini, gunakan penyelesaian lain untuk port di bawah.
Amaran! Jika anda menggunakan sendMessage, anda juga boleh melaksanakan penyelesaian untuk sendMessage (di bawah).
manifest.json, bahagian yang berkaitan:
"permissions": ["scripting"],
"host_permissions": ["<all_urls>"],
"background": {"service_worker": "bg.js"}
Pekerja perkhidmatan latar belakang bg.js:
const onUpdate = (tabId, info, tab) => /^https?:/.test(info.url) && findTab([tab]);
findTab();
chrome.runtime.onConnect.addListener(port => {
if (port.name === 'keepAlive') {
setTimeout(() => port.disconnect(), 250e3);
port.onDisconnect.addListener(() => findTab());
}
});
async function findTab(tabs) {
if (chrome.runtime.lastError) { /* tab was closed before setTimeout ran */ }
for (const {id: tabId} of tabs || await chrome.tabs.query({url: '*://*/*'})) {
try {
await chrome.scripting.executeScript({target: {tabId}, func: connect});
chrome.tabs.onUpdated.removeListener(onUpdate);
return;
} catch (e) {}
}
chrome.tabs.onUpdated.addListener(onUpdate);
}
function connect() {
chrome.runtime.connect({name: 'keepAlive'})
.onDisconnect.addListener(connect);
}
Semua halaman sambungan lain seperti pop timbul atau pilihan:
;(function connect() {
chrome.runtime.connect({name: 'keepAlive'})
.onDisconnect.addListener(connect);
})();
Dalam Chrome 99-101, anda perlu sentiasa memanggil sendResponse() dalam pendengar chrome.runtime.onMessage walaupun respons tidak diperlukan. Ini adalah pepijat dalam MV3. Selain itu, pastikan anda melakukan ini dalam masa 5 minit, jika tidak, hubungi sendResponse dengan segera dan hantar mesej baharu melalui chrome.tabs.sendMessage (ke tab) atau chrome.runtime.sendMessage (ke pop timbul) apabila kerja selesai.
Amaran! Jika anda turut menyambungkan lebih banyak port kepada pekerja perkhidmatan, anda perlu menyambung semula setiap port sebelum 5 minit berlalu, contohnya, dalam masa 295 saat. Ini adalah kritikal dalam versi Chrome sebelum 104, yang akan membunuh SW tidak kira berapa banyak port sambungan tambahan yang ada. Dalam Chrome 104 dan ke atas pepijat ini telah diperbaiki, tetapi anda masih perlu menyambungkannya semula kerana kitaran hayat 5 minit mereka tidak berubah, jadi penyelesaian paling mudah ialah menyambungkannya semula dengan cara yang sama dalam semua versi Sambungan Chrome: contohnya setiap 295 saat .
Contoh skrip belakang:
chrome.runtime.onConnect.addListener(port => { if (port.name !== 'foo') return; port.onMessage.addListener(onMessage); port.onDisconnect.addListener(deleteTimer); port._timer = setTimeout(forceReconnect, 250e3, port); }); function onMessage(msg, port) { console.log('received', msg, 'from', port.sender); } function forceReconnect(port) { deleteTimer(port); port.disconnect(); } function deleteTimer(port) { if (port._timer) { clearTimeout(port._timer); delete port._timer; } }
Contoh skrip pelanggan, seperti skrip kandungan:
let port;
function connect() {
port = chrome.runtime.connect({name: 'foo'});
port.onDisconnect.addListener(connect);
port.onMessage.addListener(msg => {
console.log('received', msg, 'from bg');
});
}
connect();
Daripada menggunakan perisian, buka tab baharu dengan halaman sambungan di dalamnya, jadi halaman ini akan bertindak sebagai "halaman latar belakang yang boleh dilihat", iaitu satu-satunya perkara yang perlu dilakukan oleh perisian ialah membuka tab ini. Anda juga boleh membukanya daripada pop timbul tindakan.
chrome.tabs.create({url: 'bg.html'})
Ia akan mempunyai fungsi yang sama seperti halaman latar belakang berterusan ManifestV2, tetapi a) ia akan kelihatan dan b) tidak akan boleh diakses melalui chrome.extension.getBackgroundPage
(boleh digantikan dengan chrome.extension.getViews).
Keburukan:
Anda boleh memudahkan pengguna dengan menambahkan maklumat/log/carta/papan pemuka pada halaman, dan juga menambah beforeunload
pendengar untuk mengelakkan tab daripada ditutup secara tidak sengaja. p>
Anda masih perlu menyimpan/memulihkan keadaan (pembolehubah) kerana tiada perkara seperti pekerja perkhidmatan yang berterusan dan penyelesaian ini mempunyai had seperti yang dinyatakan di atas supaya pekerja itu boleh ditamatkan perkhidmatan. Anda boleh mengekalkan keadaan dalam simpanan, Contoh.
Sila ambil perhatian bahawa anda tidak seharusnya membuat rangkaian pekerja anda berterusan hanya untuk memudahkan pengurusan keadaan/pembolehubah. Ini hanya dilakukan untuk memulihkan prestasi yang lebih teruk dengan memulakan semula benang pekerja, sekiranya keadaan anda sangat mahal untuk dibina semula, atau jika anda terpengaruh dengan acara yang kerap disenaraikan pada permulaan jawapan ini.