Behandel evenementen met servicemedewerkers

Zelfstudie waarin de concepten van extensieservicemedewerkers worden behandeld

Overzicht

Deze tutorial biedt een inleiding tot medewerkers van de Chrome Extension-service. Als onderdeel van deze zelfstudie bouwt u een extensie waarmee gebruikers snel naar Chrome API-referentiepagina's kunnen navigeren met behulp van de omnibox. Je leert hoe je:

  • Registreer uw servicemedewerker en importeer modules.
  • Debug uw extensieservicemedewerker.
  • Beheer de status en handel gebeurtenissen af.
  • Activeer periodieke gebeurtenissen.
  • Communiceer met inhoudsscripts.

Voordat je begint

In deze handleiding wordt ervan uitgegaan dat u over basiservaring op het gebied van webontwikkeling beschikt. We raden u aan Extensies 101 en Hello World te raadplegen voor een inleiding tot de ontwikkeling van extensies.

Bouw de extensie

Begin met het maken van een nieuwe map met de naam quick-api-reference om de extensiebestanden te bewaren, of download de broncode 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 servicemedewerker in het manifest, waarvoor slechts één JavaScript-bestand nodig is. Het is niet nodig om navigator.serviceWorker.register() aan te roepen, zoals u dat op een webpagina zou doen.

Maak een map images en download de pictogrammen daarin.

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

Stap 2: Importeer meerdere servicemedewerkermodules

Onze servicemedewerker implementeert twee functies. Voor een betere onderhoudbaarheid zullen we elke feature in een aparte module implementeren. Eerst moeten we de servicemedewerker als ES-module in ons manifest declareren, waardoor we modules in onze servicemedewerker kunnen importeren:

manifest.json:

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

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

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

Maak deze bestanden en voeg aan elk 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 servicemedewerker te importeren.

Optioneel: fouten opsporen in de servicemedewerker

Ik zal uitleggen hoe je de logboeken van de servicemedewerkers kunt vinden en weten wanneer deze zijn beëindigd. Volg eerst de instructies om een ​​uitgepakte extensie te laden .

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

Is het je opgevallen dat de inspectie van de servicemedewerker hem wakker heeft gemaakt? Als u de servicemedewerker in devtools opent, blijft deze actief. Om ervoor te zorgen dat uw extensie zich correct gedraagt ​​wanneer uw servicemedewerker wordt beëindigd, moet u DevTools afsluiten.

Verbreek nu de extensie om te zien waar u fouten kunt vinden. Eén 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 servicemedewerker niet registreren.

Ga terug naar chrome://extensions en vernieuw de extensie. U zult twee fouten zien:

Service worker registration failed. Status code: 3.

An unknown error occurred when fetching the script.

Zie Foutopsporing in extensies voor meer manieren om fouten op te sporen in de extensieservicewerknemer.

Stap 4: Initialiseer de staat

Chrome sluit servicemedewerkers af als ze niet nodig zijn. We gebruiken de chrome.storage API om de status tijdens servicewerksessies te behouden. Voor opslagtoegang moeten we toestemming vragen in het manifest:

manifest.json:

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

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

sw-omnibox.js:

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

Servicemedewerkers hebben geen directe toegang tot het window-object en kunnen daarom window.localStorage niet gebruiken om waarden op te slaan. Bovendien zijn servicemedewerkers slechts kortstondige uitvoeringsomgevingen; ze worden herhaaldelijk beëindigd tijdens de browsersessie van een gebruiker, waardoor ze incompatibel 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 voor meer informatie over andere opslagopties voor medewerkers van de uitbreidingsservice.

Stap 5: Registreer uw evenementen

Alle gebeurtenislisteners moeten statisch worden geregistreerd in het globale bereik van de servicemedewerker. Met andere woorden: gebeurtenislisteners mogen niet worden genest in asynchrone functies. Op deze manier kan Chrome ervoor zorgen dat alle gebeurtenishandlers worden hersteld in het geval dat een servicemedewerker opnieuw opstart.

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

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 spatie, geeft Chrome een lijst met suggesties weer op basis van de trefwoorden in de opslag. De gebeurtenis onInputChanged() , die de huidige gebruikersinvoer en een suggestResult object nodig heeft, 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 gebruikt worden als omnibox-suggestie.

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 terugkerend evenement in

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

Begin met het aanvragen van de toestemming "alarms" in het manifest. Om de extensietips van een externe gehoste locatie op te halen, moet u bovendien hosttoestemming aanvragen:

manifest.json:

{
  ...
  "permissions": ["storage"],
  "permissions": ["storage", "alarms"],
  "host_permissions": ["https://extension-tips.glitch.me/*"],
}

De extensie haalt alle tips op, kiest er willekeurig een en slaat deze op in de opslag. We zullen een alarm creëren dat één keer per dag wordt geactiveerd om de tip bij te werken. Alarmen worden niet opgeslagen wanneer u Chrome sluit. We moeten dus controleren of het alarm bestaat en het aanmaken als dat niet het geval is.

sw-tips.js:

// Fetch tip & save in storage
const updateTip = async () => {
  const response = await fetch('https://extension-tips.glitch.me/tips.json');
  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 inhoudsscripts om de inhoud van de pagina te lezen en aan te passen. Wanneer een gebruiker een Chrome API-referentiepagina bezoekt, werkt het inhoudsscript van de extensie de pagina bij met de tip van de dag. Er wordt een bericht verzonden om de fooi van de dag aan de servicemedewerker te vragen.

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

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 servicemedewerker met het verzoek om de fooi. Voeg vervolgens een knop toe waarmee een popover wordt geopend met daarin de extensietip. Deze code maakt gebruik van het nieuwe webplatform Popover API .

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 berichtenhandler aan onze servicemedewerker die een antwoord op het inhoudsscript 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: map afbeeldingen, manifest.json, service-worker.js, sw-omnibox.js, sw-tips.js en content.js

Laad uw extensie lokaal

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

Open een referentiepagina

  1. Voer het trefwoord "api" in de adresbalk van de 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 Chrome API-referentiepagina.

Het zou er zo uit moeten zien:

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

Open de tip van de dag

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

Dagelijks geopend tip-in
Snelle API-extensie die de tip van de dag opent.

🎯 Mogelijke verbeteringen

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

  • Ontdek een andere manier om de omnibox-suggesties te implementeren.
  • Creëer uw eigen aangepaste modaliteit voor het weergeven van de extensietip.
  • Open een extra pagina voor de referentie-API-pagina's voor webextensies van MDN.

Blijf bouwen!

Gefeliciteerd met het voltooien van deze tutorial 🎉. Ga door met het verbeteren van je vaardigheden door andere tutorials voor beginners te voltooien:

Verlenging Wat je gaat leren
Leestijd Om automatisch een element op een specifieke reeks pagina's in te voegen.
Tabbladenbeheer Om een ​​pop-up te maken die browsertabbladen beheert.
Focusmodus Om code uit te voeren op de huidige pagina nadat u op de extensieactie heeft geklikt.

Ga door met verkennen

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