Išsamus vadovas, kaip perkelti naršyklės plėtinio foninį skriptą į „JavaScript Service Worker“, apimantis privalumus, iššūkius ir geriausias praktikas.
Naršyklės Plėtinių Foniniai Skriptai: Perėjimas prie JavaScript Service Worker
Naršyklės plėtinių kūrimo aplinka nuolat keičiasi. Vienas iš reikšmingiausių pastarųjų pokyčių yra perėjimas nuo tradicinių nuolatinių foninių puslapių prie „JavaScript Service Workers“ foniniams skriptams. Ši migracija, daugiausia nulemta „Manifest V3“ (MV3) „Chromium“ pagrindu veikiančiose naršyklėse, suteikia daug privalumų, tačiau taip pat kelia unikalių iššūkių kūrėjams. Šiame išsamiame vadove gilinsimės į šio pokyčio priežastis, privalumus ir trūkumus bei išsamiai apžvelgsime migracijos procesą, užtikrindami sklandų jūsų plėtinio perėjimą.
Kodėl verta pereiti prie „Service Workers“?
Pagrindinė šio perėjimo motyvacija – pagerinti naršyklės našumą ir saugumą. Nuolatiniai foniniai puslapiai, kurie buvo įprasti „Manifest V2“ (MV2), gali sunaudoti daug resursų net ir būdami neaktyvūs, o tai neigiamai veikia baterijos veikimo laiką ir bendrą naršyklės reakcijos greitį. Kita vertus, „Service Workers“ yra valdomi įvykiais ir aktyvūs tik tada, kai to reikia.
„Service Workers“ privalumai:
- Pagerintas našumas: „Service Workers“ yra aktyvūs tik tada, kai juos sužadina įvykis, pavyzdžiui, API iškvietimas ar pranešimas iš kitos plėtinio dalies. Šis „įvykiais valdomas“ pobūdis sumažina resursų suvartojimą ir pagerina naršyklės našumą.
- Padidintas saugumas: „Service Workers“ veikia labiau apribotoje aplinkoje, sumažindami atakos galimybes ir pagerindami bendrą plėtinio saugumą.
- Ateities perspektyva: Dauguma pagrindinių naršyklių pereina prie „Service Workers“ kaip standarto foniniam apdorojimui plėtiniuose. Migracija dabar užtikrina, kad jūsų plėtinys išliks suderinamas ir išvengs ateities pasenimo problemų.
- Neblokuojančios operacijos: „Service Workers“ yra sukurti atlikti užduotis fone, neblokuojant pagrindinės gijos, taip užtikrinant sklandesnę vartotojo patirtį.
Trūkumai ir iššūkiai:
- Mokymosi kreivė: „Service Workers“ įveda naują programavimo modelį, kuris gali būti sudėtingas kūrėjams, pripratusiems prie nuolatinių foninių puslapių. Įvykiais valdomas pobūdis reikalauja kitokio požiūrio į būsenos valdymą ir komunikaciją.
- Nuolatinės būsenos valdymas: Norint išlaikyti nuolatinę būseną tarp „Service Worker“ aktyvacijų, reikia atidžiai apsvarstyti. Technikos, tokios kaip „Storage API“ ar „IndexedDB“, tampa labai svarbios.
- Derinimo sudėtingumas: Derinti „Service Workers“ gali būti sudėtingiau nei tradicinius foninius puslapius dėl jų pertraukiamo pobūdžio.
- Ribota prieiga prie DOM: „Service Workers“ negali tiesiogiai pasiekti DOM. Jie turi bendrauti su turinio skriptais, kad galėtų sąveikauti su tinklalapiais.
Pagrindinių koncepcijų supratimas
Prieš pradedant migracijos procesą, būtina suprasti pagrindines „Service Workers“ koncepcijas:
Gyvavimo ciklo valdymas
„Service Workers“ turi aiškų gyvavimo ciklą, susidedantį iš šių etapų:
- Įdiegimas: „Service Worker“ įdiegiamas, kai plėtinys pirmą kartą įkeliamas arba atnaujinamas. Tai idealus laikas kešuoti statinius išteklius ir atlikti pradines sąrankos užduotis.
- Aktyvavimas: Po įdiegimo „Service Worker“ yra aktyvuojamas. Tai taškas, kuriame jis gali pradėti tvarkyti įvykius.
- Neaktyvus: „Service Worker“ lieka neaktyvus, laukdamas jį sužadinančių įvykių.
- Nutraukimas: „Service Worker“ nutraukiamas, kai jo nebereikia.
Įvykiais valdoma architektūra
„Service Workers“ yra valdomi įvykiais, o tai reiškia, kad jie vykdo kodą tik reaguodami į konkrečius įvykius. Dažniausi įvykiai:
- install: Sužadinamas, kai „Service Worker“ yra įdiegiamas.
- activate: Sužadinamas, kai „Service Worker“ yra aktyvuojamas.
- fetch: Sužadinamas, kai naršyklė pateikia tinklo užklausą.
- message: Sužadinamas, kai „Service Worker“ gauna pranešimą iš kitos plėtinio dalies.
Tarpprocesinė komunikacija
„Service Workers“ turi turėti būdą bendrauti su kitomis plėtinio dalimis, pavyzdžiui, turinio skriptais ir iškylančiųjų langų (popup) skriptais. Paprastai tai pasiekiama naudojant chrome.runtime.sendMessage ir chrome.runtime.onMessage API.
Žingsnis po žingsnio migracijos vadovas
Pereikime per tipinio naršyklės plėtinio perkėlimo iš nuolatinio foninio puslapio į „Service Worker“ procesą.
1 žingsnis: Atnaujinkite savo „Manifest“ failą (manifest.json)
Pirmasis žingsnis yra atnaujinti jūsų manifest.json failą, kad jis atspindėtų perėjimą prie „Service Worker“. Pašalinkite "background" lauką ir pakeiskite jį "background" lauku, kuriame yra "service_worker" savybė.
Manifest V2 pavyzdys (nuolatinis foninis puslapis):
{
"manifest_version": 2,
"name": "My Extension",
"version": "1.0",
"background": {
"scripts": ["background.js"],
"persistent": true
},
"permissions": [
"storage",
"activeTab"
]
}
Manifest V3 pavyzdys („Service Worker“):
{
"manifest_version": 3,
"name": "My Extension",
"version": "1.0",
"background": {
"service_worker": "background.js"
},
"permissions": [
"storage",
"activeTab"
]
}
Svarbūs aspektai:
- Užtikrinkite, kad jūsų
manifest_versionbūtų nustatytas į 3. "service_worker"savybė nurodo kelią į jūsų „Service Worker“ skriptą.
2 žingsnis: Pertvarkykite savo foninį skriptą (background.js)
Tai yra pats svarbiausias migracijos proceso žingsnis. Jums reikia pertvarkyti savo foninį skriptą, kad jis prisitaikytų prie įvykiais valdomo „Service Workers“ pobūdžio.
1. Pašalinkite nuolatinės būsenos kintamuosius
MV2 foniniuose puslapiuose galėjote pasikliauti globaliais kintamaisiais, kad išlaikytumėte būseną tarp skirtingų įvykių. Tačiau „Service Workers“ yra nutraukiami, kai yra neaktyvūs, todėl globalūs kintamieji nėra patikimi nuolatinei būsenai palaikyti.
Pavyzdys (MV2):
var counter = 0;
chrome.browserAction.onClicked.addListener(function(tab) {
counter++;
console.log("Counter: " + counter);
});
Sprendimas: Naudokite „Storage API“ arba „IndexedDB“
„Storage API“ (chrome.storage.local arba chrome.storage.sync) leidžia nuolat saugoti ir gauti duomenis. „IndexedDB“ yra kita galimybė sudėtingesnėms duomenų struktūroms.
Pavyzdys (MV3 su „Storage API“):
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.storage.local.get(['counter'], function(result) {
var counter = result.counter || 0;
counter++;
chrome.storage.local.set({counter: counter}, function() {
console.log("Counter: " + counter);
});
});
});
Pavyzdys (MV3 su „IndexedDB“):
// Function to open the IndexedDB database
function openDatabase() {
return new Promise((resolve, reject) => {
const request = indexedDB.open('myDatabase', 1);
request.onerror = (event) => {
reject('Error opening database');
};
request.onsuccess = (event) => {
resolve(event.target.result);
};
request.onupgradeneeded = (event) => {
const db = event.target.result;
db.createObjectStore('myObjectStore', { keyPath: 'id' });
};
});
}
// Function to get data from IndexedDB
function getData(db, id) {
return new Promise((resolve, reject) => {
const transaction = db.transaction(['myObjectStore'], 'readonly');
const objectStore = transaction.objectStore('myObjectStore');
const request = objectStore.get(id);
request.onerror = (event) => {
reject('Error getting data');
};
request.onsuccess = (event) => {
resolve(request.result);
};
});
}
// Function to put data into IndexedDB
function putData(db, data) {
return new Promise((resolve, reject) => {
const transaction = db.transaction(['myObjectStore'], 'readwrite');
const objectStore = transaction.objectStore('myObjectStore');
const request = objectStore.put(data);
request.onerror = (event) => {
reject('Error putting data');
};
request.onsuccess = (event) => {
resolve();
};
});
}
chrome.browserAction.onClicked.addListener(async (tab) => {
try {
const db = await openDatabase();
let counterData = await getData(db, 'counter');
let counter = counterData ? counterData.value : 0;
counter++;
await putData(db, { id: 'counter', value: counter });
db.close();
console.log("Counter: " + counter);
} catch (error) {
console.error("IndexedDB Error: ", error);
}
});
2. Pakeiskite įvykių klausytojus pranešimų perdavimu
Jei jūsų foninis skriptas bendrauja su turinio skriptais ar kitomis plėtinio dalimis, jums reikės naudoti pranešimų perdavimą.
Pavyzdys (pranešimo siuntimas iš foninio skripto į turinio skriptą):
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if (request.message === "get_data") {
// Do something to retrieve data
let data = "Example Data";
sendResponse({data: data});
}
}
);
Pavyzdys (pranešimo siuntimas iš turinio skripto į foninį skriptą):
chrome.runtime.sendMessage({message: "get_data"}, function(response) {
console.log("Received data: " + response.data);
});
3. Atlikite inicializavimo užduotis `install` įvykio metu
install įvykis sužadinamas, kai „Service Worker“ pirmą kartą įdiegiamas arba atnaujinamas. Tai puiki vieta atlikti inicializavimo užduotis, tokias kaip duomenų bazių kūrimas ar statinių išteklių kešavimas.
Pavyzdys:
chrome.runtime.onInstalled.addListener(function() {
console.log("Service Worker installed.");
// Perform initialization tasks here
chrome.storage.local.set({initialized: true});
});
4. Apsvarstykite „Offscreen“ dokumentus
„Manifest V3“ pristatė „offscreen“ dokumentus, skirtus atlikti užduotis, kurios anksčiau reikalavo DOM prieigos foniniuose puslapiuose, pavyzdžiui, garso atkūrimas ar sąveika su iškarpine. Šie dokumentai veikia atskirame kontekste, bet gali sąveikauti su DOM „service worker“ vardu.
Jei jūsų plėtiniui reikia plačiai manipuliuoti DOM arba atlikti užduotis, kurios nėra lengvai pasiekiamos naudojant pranešimų perdavimą ir turinio skriptus, „offscreen“ dokumentai gali būti tinkamas sprendimas.
Pavyzdys („Offscreen“ dokumento kūrimas):
// In your background script:
async function createOffscreen() {
if (await chrome.offscreen.hasDocument({
reasons: [chrome.offscreen.Reason.WORKER],
justification: 'reason for needing the document'
})) {
return;
}
await chrome.offscreen.createDocument({
url: 'offscreen.html',
reasons: [chrome.offscreen.Reason.WORKER],
justification: 'reason for needing the document'
});
}
chrome.runtime.onStartup.addListener(createOffscreen);
chrome.runtime.onInstalled.addListener(createOffscreen);
Pavyzdys (offscreen.html):
<!DOCTYPE html>
<html>
<head>
<title>Offscreen Document</title>
</head>
<body>
<script src="offscreen.js"></script>
</body>
</html>
Pavyzdys (offscreen.js, kuris veikia „offscreen“ dokumente):
// Listen for messages from the service worker
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.action === 'doSomething') {
// Do something with the DOM here
document.body.textContent = 'Action performed!';
sendResponse({ result: 'success' });
}
});
3 žingsnis: Kruopščiai išbandykite savo plėtinį
Pertvarkius foninį skriptą, labai svarbu kruopščiai išbandyti savo plėtinį, siekiant užtikrinti, kad jis tinkamai veiktų naujoje „Service Worker“ aplinkoje. Atkreipkite ypatingą dėmesį į šias sritis:
- Būsenos valdymas: Patikrinkite, ar jūsų nuolatinė būsena yra teisingai saugoma ir gaunama naudojant „Storage API“ arba „IndexedDB“.
- Pranešimų perdavimas: Užtikrinkite, kad pranešimai yra teisingai siunčiami ir gaunami tarp foninio skripto, turinio skriptų ir iškylančiųjų langų (popup) skriptų.
- Įvykių tvarkymas: Išbandykite visus įvykių klausytojus, kad įsitikintumėte, jog jie sužadinami kaip tikėtasi.
- Našumas: Stebėkite savo plėtinio našumą, kad įsitikintumėte, jog jis nesunaudoja per daug resursų.
4 žingsnis: „Service Workers“ derinimas
„Service Workers“ derinimas gali būti sudėtingas dėl jų pertraukiamo pobūdžio. Štai keletas patarimų, kurie padės jums derinti savo „Service Worker“:
- „Chrome DevTools“: Naudokite „Chrome DevTools“ norėdami patikrinti „Service Worker“, peržiūrėti konsolės žurnalus ir nustatyti lūžio taškus. „Service Worker“ galite rasti skirtuke „Application“.
- Nuolatiniai konsolės žurnalai: Gausiai naudokite
console.logteiginius, kad sektumėte savo „Service Worker“ vykdymo eigą. - Lūžio taškai: Nustatykite lūžio taškus savo „Service Worker“ kode, kad sustabdytumėte vykdymą ir patikrintumėte kintamuosius.
- „Service Worker Inspector“: Naudokite „Service Worker“ inspektorių „Chrome DevTools“, kad peržiūrėtumėte „Service Worker“ būseną, įvykius ir tinklo užklausas.
Geriausios praktikos „Service Worker“ migracijai
Štai keletas geriausių praktikų, kurių reikėtų laikytis perkeliant naršyklės plėtinį į „Service Workers“:
- Pradėkite anksti: Nelaukite paskutinės minutės, kad pereitumėte prie „Service Workers“. Pradėkite migracijos procesą kuo anksčiau, kad turėtumėte pakankamai laiko pertvarkyti kodą ir išbandyti plėtinį.
- Suskirstykite užduotį: Suskirstykite migracijos procesą į mažesnes, valdomas užduotis. Tai padarys procesą mažiau bauginantį ir lengviau sekamą.
- Dažnai testuokite: Dažnai testuokite savo plėtinį viso migracijos proceso metu, kad anksti pastebėtumėte klaidas.
- Naudokite „Storage API“ arba „IndexedDB“ nuolatinei būsenai: Nesikliaukite globaliais kintamaisiais nuolatinei būsenai. Vietoj to naudokite „Storage API“ arba „IndexedDB“.
- Naudokite pranešimų perdavimą komunikacijai: Naudokite pranešimų perdavimą, kad bendrautumėte tarp foninio skripto, turinio skriptų ir iškylančiųjų langų (popup) skriptų.
- Optimizuokite savo kodą: Optimizuokite savo kodą našumui, kad sumažintumėte resursų suvartojimą.
- Apsvarstykite „Offscreen“ dokumentus: Jei jums reikia plačiai manipuliuoti DOM, apsvarstykite galimybę naudoti „offscreen“ dokumentus.
Tarptautinimo aspektai
Kuriant naršyklės plėtinius pasaulinei auditorijai, labai svarbu atsižvelgti į tarptautinimą (i18n) ir lokalizavimą (l10n). Štai keletas patarimų, kaip užtikrinti, kad jūsų plėtinys būtų prieinamas vartotojams visame pasaulyje:
- Naudokite `_locales` aplanką: Saugokite savo plėtinio išverstas eilutes `_locales` aplanke. Šiame aplanke yra poaplankiai kiekvienai palaikomai kalbai su `messages.json` failu, kuriame yra vertimai.
- Naudokite `__MSG_messageName__` sintaksę: Naudokite `__MSG_messageName__` sintaksę, norėdami nurodyti išverstas eilutes savo kode ir „manifest“ faile.
- Palaikykite kalbas, rašomas iš dešinės į kairę (RTL): Užtikrinkite, kad jūsų plėtinio išdėstymas ir stilius tinkamai prisitaikytų prie RTL kalbų, tokių kaip arabų ir hebrajų.
- Atsižvelkite į datos ir laiko formatavimą: Naudokite tinkamą datos ir laiko formatavimą kiekvienai lokalizacijai.
- Pateikite kultūriškai aktualų turinį: Pritaikykite savo plėtinio turinį, kad jis būtų kultūriškai aktualus skirtingiems regionams.
Pavyzdys (_locales/en/messages.json):
{
"extensionName": {
"message": "My Extension",
"description": "The name of the extension"
},
"buttonText": {
"message": "Click Me",
"description": "The text for the button"
}
}
Pavyzdys (nurodant išverstas eilutes jūsų kode):
document.getElementById('myButton').textContent = chrome.i18n.getMessage("buttonText");
Išvados
Naršyklės plėtinio foninio skripto perkėlimas į „JavaScript Service Worker“ yra svarbus žingsnis siekiant pagerinti našumą, saugumą ir užtikrinti plėtinio ateities perspektyvą. Nors perėjimas gali kelti tam tikrų iššūkių, nauda yra verta pastangų. Vadovaudamiesi šiame vadove pateiktais žingsniais ir taikydami geriausias praktikas, galite užtikrinti sklandžią ir sėkmingą migraciją, suteikdami geresnę patirtį savo vartotojams visame pasaulyje. Nepamirškite kruopščiai testuoti ir prisitaikyti prie naujos įvykiais valdomos architektūros, kad galėtumėte visapusiškai išnaudoti „Service Workers“ galią.