Behandel evenementen met servicemedewerkers

Tutorial die de concepten van extensiedienstmedewerkers behandelt

Overzicht

Deze tutorial biedt een introductie tot serviceworkers voor Chrome-extensies. Als onderdeel van deze tutorial bouwt u een extensie waarmee gebruikers snel naar Chrome API-referentiepagina's kunnen navigeren via de omnibox. U leert het volgende:

  • Registreer uw service worker en importeer modules.
  • Debug uw extensieservicemedewerker.
  • Beheer de status en verwerk gebeurtenissen.
  • Periodieke gebeurtenissen activeren.
  • Communiceer met inhoudsscripts.

Voordat je begint

Deze handleiding gaat ervan uit dat je basiservaring hebt met webontwikkeling. We raden je aan Extensions 101 en Hello World te bekijken voor een introductie tot extensieontwikkeling.

Bouw de extensie

Begin met het maken van een nieuwe map met de naam quick-api-reference om de extensiebestanden in op te slaan. U kunt ook de broncode downloaden uit onze GitHub- voorbeeldrepository.

Stap 1: Registreer de servicemedewerker

Maak het manifestbestand in de hoofdmap van het project en voeg de volgende code toe:

manifest.json:

{   "manifest_version": 3,   "name": "Open extension API reference",   "version": "1.0.0",   "icons": {     "16": "images/icon-16.png",     "128": "images/icon-128.png"   },   "background": {     "service_worker": "service-worker.js"   } } 

Extensies registreren hun service worker in het manifest, waarvoor slechts één JavaScript-bestand nodig is. Het is niet nodig om navigator.serviceWorker.register() aan te roepen, zoals op een webpagina.

Maak een map images en download de pictogrammen daarin.

Bekijk de eerste stappen van de tutorial Leestijd voor meer informatie over de metagegevens en pictogrammen van de extensie in het manifest.

Stap 2: Importeer meerdere service worker-modules

Onze service worker implementeert twee functies. Voor een beter onderhoud implementeren we elke functie in een aparte module. Eerst moeten we de service worker declareren als een ES-module in ons manifest, zodat we modules in onze service worker kunnen importeren:

manifest.json:

{  "background": {     "service_worker": "service-worker.js",     "type": "module"   }, } 

Maak het bestand service-worker.js en importeer twee modules:

import './sw-omnibox.js'; import './sw-tips.js'; 

Maak deze bestanden aan en voeg aan elk bestand een consolelogboek toe.

sw-omnibox.js:

console.log("sw-omnibox.js");

sw-tips.js:

console.log("sw-tips.js");

Zie Scripts importeren voor meer informatie over andere manieren om meerdere bestanden in een service worker te importeren.

Optioneel: de service worker debuggen

Ik leg uit hoe je de logs van de service worker kunt vinden en kunt zien wanneer deze beëindigd is. Volg eerst de instructies om een ​​uitgepakte extensie te laden .

Na 30 seconden ziet u "service worker (inactief)", wat betekent dat de service worker is beëindigd. Klik op de link "service worker (inactief)" om deze te bekijken. De volgende animatie laat dit zien.

Heb je gemerkt dat het inspecteren van de service worker hem wakker maakte? Door de service worker in de DevTools te openen, blijft hij actief. Om ervoor te zorgen dat je extensie correct functioneert wanneer je service worker wordt beëindigd, vergeet dan niet DevTools te sluiten.

Breek nu de extensie om te achterhalen waar de fouten zich bevinden. Een manier om dit te doen is door ".js" te verwijderen uit de import './sw-omnibox.js' in het bestand service-worker.js . Chrome kan de service worker dan niet registreren.

Ga terug naar chrome://extensions en vernieuw de extensie. Je ziet twee foutmeldingen:

Service worker registration failed. Status code: 3.  An unknown error occurred when fetching the script. 

Zie Extensies debuggen voor meer manieren om de extensieserviceworker te debuggen.

Stap 4: Initialiseer de status

Chrome sluit service workers af als ze niet nodig zijn. We gebruiken de chrome.storage API om de status te behouden tijdens service worker-sessies. Voor toegang tot de opslag moeten we toestemming vragen in het manifest:

manifest.json:

{   ...   "permissions": ["storage"], } 

Sla eerst de standaard suggesties op in de opslag. We kunnen de status initialiseren wanneer de extensie voor het eerst wordt geïnstalleerd door te luisteren naar de runtime.onInstalled() -gebeurtenis:

sw-omnibox.js:

... // Save default API suggestions chrome.runtime.onInstalled.addListener(({ reason }) => {   if (reason === 'install') {     chrome.storage.local.set({       apiSuggestions: ['tabs', 'storage', 'scripting']     });   } }); 

Service workers hebben geen directe toegang tot het vensterobject en kunnen daarom window.localStorage niet gebruiken om waarden op te slaan. Bovendien zijn service workers kortdurende uitvoeringsomgevingen; ze worden herhaaldelijk beëindigd tijdens de browsersessie van een gebruiker, waardoor ze niet compatibel zijn met globale variabelen. Gebruik in plaats daarvan chrome.storage.local , waarmee gegevens op de lokale computer worden opgeslagen.

Zie Gegevens behouden in plaats van globale variabelen te gebruiken om meer te weten te komen over andere opslagopties voor medewerkers van uitbreidingsdiensten.

Stap 5: Registreer uw evenementen

Alle event listeners moeten statisch geregistreerd zijn in de globale scope van de service worker. Met andere woorden: event listeners mogen niet genest worden in asynchrone functies. Zo kan Chrome ervoor zorgen dat alle event handlers hersteld worden bij een herstart van de service worker.

In dit voorbeeld gaan we de chrome.omnibox API gebruiken, maar eerst moeten we het omnibox-trefwoord 'trigger' declareren in het manifest:

manifest.json:

{   ...   "minimum_chrome_version": "102",   "omnibox": {     "keyword": "api"   }, } 

Registreer nu de omnibox-gebeurtenislisteners op het hoogste niveau van het script. Wanneer de gebruiker het omnibox-trefwoord ( api ) in de adresbalk invoert, gevolgd door een tab- of spatiebalk, toont Chrome een lijst met suggesties op basis van de trefwoorden in de opslag. De onInputChanged() -gebeurtenis, die de huidige gebruikersinvoer en een suggestResult object gebruikt, is verantwoordelijk voor het invullen van deze suggesties.

sw-omnibox.js:

... const URL_CHROME_EXTENSIONS_DOC =   'https://developer.chrome.com/docs/extensions/reference/'; const NUMBER_OF_PREVIOUS_SEARCHES = 4;  // Display the suggestions after user starts typing chrome.omnibox.onInputChanged.addListener(async (input, suggest) => {   await chrome.omnibox.setDefaultSuggestion({     description: 'Enter a Chrome API or choose from past searches'   });   const { apiSuggestions } = await chrome.storage.local.get('apiSuggestions');   const suggestions = apiSuggestions.map((api) => {     return { content: api, description: `Open chrome.${api} API` };   });   suggest(suggestions); }); 

Nadat de gebruiker een suggestie heeft geselecteerd, opent onInputEntered() de bijbehorende Chrome API-referentiepagina.

sw-omnibox.js:

... // Open the reference page of the chosen API chrome.omnibox.onInputEntered.addListener((input) => {   chrome.tabs.create({ url: URL_CHROME_EXTENSIONS_DOC + input });   // Save the latest keyword   updateHistory(input); }); 

De functie updateHistory() neemt de omnibox-invoer en slaat deze op in storage.local . Zo kan de meest recente zoekterm later als omnibox-suggestie worden gebruikt.

sw-omnibox.js:

... async function updateHistory(input) {   const { apiSuggestions } = await chrome.storage.local.get('apiSuggestions');   apiSuggestions.unshift(input);   apiSuggestions.splice(NUMBER_OF_PREVIOUS_SEARCHES);   return chrome.storage.local.set({ apiSuggestions }); } 

Stap 6: Stel een terugkerende gebeurtenis in

De methoden setTimeout() en setInterval() worden vaak gebruikt om vertraagde of periodieke taken uit te voeren. Deze API's kunnen echter mislukken omdat de scheduler de timers annuleert wanneer de service worker wordt beëindigd. In plaats daarvan kunnen extensies de chrome.alarms API gebruiken.

Begin met het aanvragen van de toestemming "alarms" in het manifest:

manifest.json:

{   ...   "permissions": ["storage"],   "permissions": ["storage", "alarms"], } 

De extensie haalt alle tips op, kiest er willekeurig één en slaat deze op in de opslagruimte. We maken een alarm aan dat eenmaal per dag afgaat om de tip bij te werken. Alarmen worden niet opgeslagen wanneer u Chrome sluit. We moeten dus controleren of het alarm bestaat en het zo niet aanmaken.

sw-tips.js:

// Fetch tip & save in storage const updateTip = async () => {   const response = await fetch('https://chrome.dev/f/extension_tips/');   const tips = await response.json();   const randomIndex = Math.floor(Math.random() * tips.length);   return chrome.storage.local.set({ tip: tips[randomIndex] }); };  const ALARM_NAME = 'tip';  // Check if alarm exists to avoid resetting the timer. // The alarm might be removed when the browser session restarts. async function createAlarm() {   const alarm = await chrome.alarms.get(ALARM_NAME);   if (typeof alarm === 'undefined') {     chrome.alarms.create(ALARM_NAME, {       delayInMinutes: 1,       periodInMinutes: 1440     });     updateTip();   } }  createAlarm();  // Update tip once a day chrome.alarms.onAlarm.addListener(updateTip); 

Stap 7: Communiceer met andere contexten

Extensies gebruiken contentscripts om de content van de pagina te lezen en te wijzigen. Wanneer een gebruiker een Chrome API-referentiepagina bezoekt, werkt het contentscript van de extensie de pagina bij met de tip van de dag. Het script stuurt een bericht om de tip van de dag op te vragen bij de service worker.

Begin met het declareren van het inhoudsscript in het manifest en voeg het matchpatroon toe dat overeenkomt met de referentiedocumentatie van de Chrome API .

manifest.json:

{   ...   "content_scripts": [     {       "matches": ["https://developer.chrome.com/docs/extensions/reference/*"],       "js": ["content.js"]     }   ] }  

Maak een nieuw inhoudsbestand. De volgende code stuurt een bericht naar de service worker met het verzoek om de tip. Vervolgens wordt een knop toegevoegd die een pop-up opent met de extensie tip. Deze code maakt gebruik van de nieuwe Popover API van het webplatform.

inhoud.js:

(async () => {   // Sends a message to the service worker and receives a tip in response   const { tip } = await chrome.runtime.sendMessage({ greeting: 'tip' });    const nav = document.querySelector('.upper-tabs > nav');      const tipWidget = createDomElement(`     <button type="button" popovertarget="tip-popover" popovertargetaction="show" style="padding: 0 12px; height: 36px;">       <span style="display: block; font: var(--devsite-link-font,500 14px/20px var(--devsite-primary-font-family));">Tip</span>     </button>   `);    const popover = createDomElement(     `<div id='tip-popover' popover style="margin: auto;">${tip}</div>`   );    document.body.append(popover);   nav.append(tipWidget); })();  function createDomElement(html) {   const dom = new DOMParser().parseFromString(html, 'text/html');   return dom.body.firstElementChild; } 

De laatste stap is het toevoegen van een berichtenverwerker aan onze service worker die een antwoord naar het content script stuurt met de dagelijkse tip.

sw-tips.js:

... // Send tip to content script via messaging chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {   if (message.greeting === 'tip') {     chrome.storage.local.get('tip').then(sendResponse);     return true;   } }); 

Test of het werkt

Controleer of de bestandsstructuur van uw project er als volgt uitziet:

De inhoud van de extensiemap: images folder, manifest.json, service-worker.js, sw-omnibox.js, sw-tips.js en content.js

Laad uw extensie lokaal

Om een ​​uitgepakte extensie in de ontwikkelaarsmodus te laden, volgt u de stappen in Hallo wereld .

Open een referentiepagina

  1. Voer het trefwoord "api" in de adresbalk van uw browser in.
  2. Druk op "tab" of "spatie".
  3. Voer de volledige naam van de API in.
    • OF kies uit een lijst met eerdere zoekopdrachten
  4. Er wordt een nieuwe pagina geopend met de referentiepagina van de Chrome API.

Het zou er zo uit moeten zien:

Snelle API-referentie: de runtime-API-referentie openen
Snelle API-extensie die de Runtime API opent.

Open de punt van de dag

Klik op de Tip-knop op de navigatiebalk om de extensietip te openen.

Dagelijkse tip openen in
Snelle API-extensie, de tip van de dag.

🎯 Mogelijke verbeteringen

Probeer op basis van wat u vandaag hebt geleerd een van de volgende dingen te bereiken:

  • Ontdek een andere manier om de omnibox-suggesties te implementeren.
  • Maak uw eigen aangepaste modale weergave voor de extensietip.
  • Open een extra pagina naar de API-referentiepagina's van MDN's Web Extensions.

Blijf bouwen!

Gefeliciteerd met het afronden van deze tutorial 🎉. Blijf je vaardigheden verbeteren door andere beginnerstutorials te volgen:

Verlenging Wat je leert
Leestijd Om automatisch een element op een specifieke set pagina's in te voegen.
Tabbladenbeheerder Om een ​​pop-up te maken waarmee u browsertabbladen kunt beheren.
Focusmodus Om code op de huidige pagina uit te voeren nadat u op de extensieactie hebt geklikt.

Blijf verkennen

Om uw leertraject voor extensiemedewerkers voort te zetten, raden wij u aan de volgende artikelen te lezen: