Anleitung zu Erweiterungs-Service-Worker-Konzepten
Übersicht
In dieser Anleitung erhalten Sie eine Einführung in Service Worker für Chrome-Erweiterungen. In dieser Anleitung erstellen Sie eine Erweiterung, mit der Nutzer über die Omnibox schnell zu Chrome API-Referenzseiten gelangen können. Nach Abschluss können Sie:
- Registrieren Sie Ihren Service Worker und importieren Sie Module.
- Fehlerbehebung für den Erweiterungsdienst-Worker
- Status verwalten und Ereignisse verarbeiten
- Regelmäßige Ereignisse auslösen
- Mit Content-Scripts kommunizieren
Vorbereitung
In diesem Leitfaden wird davon ausgegangen, dass Sie grundlegende Erfahrung mit der Webentwicklung haben. Eine Einführung in die Erweiterungsentwicklung finden Sie unter Erweiterungen – Grundlagen und Hallo Welt.
Erweiterung erstellen
Erstellen Sie zuerst ein neues Verzeichnis namens quick-api-reference
für die Erweiterungsdateien oder laden Sie den Quellcode aus unserem GitHub-Repository mit Beispielen herunter.
Schritt 1: Service Worker registrieren
Erstellen Sie die Datei manifest im Stammverzeichnis des Projekts und fügen Sie den folgenden Code hinzu:
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"
}
}
Erweiterungen registrieren ihren Dienst-Worker im Manifest, für das nur eine einzige JavaScript-Datei erforderlich ist.
Sie müssen navigator.serviceWorker.register()
nicht aufrufen, wie Sie es auf einer Webseite tun würden.
Erstellen Sie einen Ordner images
und laden Sie die Symbole in diesen Ordner herunter.
In den ersten Schritten der Anleitung für die Lesezeit erfahren Sie mehr über die metadata und Symbole der Erweiterung im Manifest.
Schritt 2: Mehrere Service Worker-Module importieren
Unser Service Worker implementiert zwei Funktionen. Aus Gründen der Wartungsfreundlichkeit werden wir jede Funktion in einem separaten Modul implementieren. Zuerst müssen wir den Service Worker in unserem Manifest als ES-Modul deklarieren, damit wir Module in unseren Service Worker importieren können:
manifest.json:
{
"background": {
"service_worker": "service-worker.js",
"type": "module"
},
}
Erstellen Sie die Datei service-worker.js
und importieren Sie zwei Module:
import './sw-omnibox.js';
import './sw-tips.js';
Erstellen Sie diese Dateien und fügen Sie jeder ein Konsolenprotokoll hinzu.
sw-omnibox.js:
console.log("sw-omnibox.js");
sw-tips.js:
console.log("sw-tips.js");
Unter Scripts importieren finden Sie weitere Informationen dazu, wie Sie mehrere Dateien in einen Service Worker importieren.
Optional: Service Worker debuggen
Ich erkläre Ihnen, wie Sie die Service Worker-Protokolle finden und erkennen, wann der Dienst beendet wurde. Folgen Sie zuerst der Anleitung zum Laden einer entpackten Erweiterung.
Nach 30 Sekunden wird „Dienst-Worker (inaktiv)“ angezeigt. Das bedeutet, dass der Dienst-Worker beendet wurde. Klicken Sie auf den Link „Dienst-Worker (inaktiv)“, um ihn zu prüfen. Das zeigt die folgende Animation.
Haben Sie bemerkt, dass der Dienst durch die Prüfung aufgeweckt wurde? Wenn Sie den Dienst-Worker in den DevTools öffnen, bleibt er aktiv. Damit sich Ihre Erweiterung nach dem Beenden des Service Workers korrekt verhält, müssen Sie die DevTools schließen.
Unterbrechen Sie jetzt die Erweiterung, um herauszufinden, wo Fehler auftreten. Eine Möglichkeit dazu besteht darin, „.js“ aus dem './sw-omnibox.js'
-Import in der service-worker.js
-Datei zu löschen. Chrome kann den Service Worker dann nicht registrieren.
Kehren Sie zu chrome://extensions zurück und aktualisieren Sie die Erweiterung. Es werden zwei Fehler angezeigt:
Service worker registration failed. Status code: 3.
An unknown error occurred when fetching the script.
Weitere Möglichkeiten zum Debuggen des Dienst-Workers der Erweiterung finden Sie unter Erweiterungen debuggen.
Schritt 4: Status initialisieren
Chrome beendet Service Worker, wenn sie nicht benötigt werden. Wir verwenden die chrome.storage
API, um den Status über Service Worker-Sitzungen hinweg zu speichern. Für den Speicherzugriff müssen wir die Berechtigung im Manifest anfordern:
manifest.json:
{
...
"permissions": ["storage"],
}
Speichern Sie zuerst die Standardvorschläge im Speicher. Wir können den Status initialisieren, wenn die Erweiterung zum ersten Mal installiert wird, indem wir das Ereignis runtime.onInstalled()
überwachen:
sw-omnibox.js:
...
// Save default API suggestions
chrome.runtime.onInstalled.addListener(({ reason }) => {
if (reason === 'install') {
chrome.storage.local.set({
apiSuggestions: ['tabs', 'storage', 'scripting']
});
}
});
Dienst-Worker haben keinen direkten Zugriff auf das Fensterobjekt und können daher keine Werte mit window.localStorage
speichern. Außerdem sind Service Worker kurzlebige Ausführungsumgebungen. Sie werden während der Browser-Sitzung eines Nutzers wiederholt beendet, was sie mit globalen Variablen inkompatibel macht. Verwenden Sie stattdessen chrome.storage.local
, mit dem Daten auf dem lokalen Computer gespeichert werden.
Weitere Informationen zu anderen Speicheroptionen für Erweiterungs-Dienstworker finden Sie unter Daten speichern, anstatt globale Variablen zu verwenden.
Schritt 5: Ereignisse registrieren
Alle Ereignis-Listener müssen global im Service Worker registriert sein. Mit anderen Worten: Ereignis-Listener sollten nicht in asynchronen Funktionen verschachtelt sein. So kann Chrome dafür sorgen, dass alle Ereignishandler bei einem Neustart des Dienstarbeiters wiederhergestellt werden.
In diesem Beispiel verwenden wir die chrome.omnibox
API. Zuerst müssen wir jedoch den Omnibox-Trigger für Suchbegriffe im Manifest deklarieren:
manifest.json:
{
...
"minimum_chrome_version": "102",
"omnibox": {
"keyword": "api"
},
}
Registrieren Sie jetzt die Omnibox-Ereignis-Listener auf der obersten Ebene des Scripts. Wenn der Nutzer das Omnibox-Keyword (api
) in die Adressleiste eingibt, gefolgt von einem Tabulator oder einem Leerzeichen, zeigt Chrome eine Liste mit Vorschlägen an, die auf den gespeicherten Keywords basieren. Das Ereignis onInputChanged()
, das die aktuelle Nutzereingabe und ein suggestResult
-Objekt berücksichtigt, ist für die Erstellung dieser Vorschläge verantwortlich.
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);
});
Nachdem der Nutzer einen Vorschlag ausgewählt hat, wird über onInputEntered()
die entsprechende Chrome API-Referenzseite geöffnet.
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);
});
Die Funktion updateHistory()
nimmt die Eingabe in der Omnibox entgegen und speichert sie in storage.local
. So kann der letzte Suchbegriff später als Omnibox-Vorschlag verwendet werden.
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 });
}
Schritt 6: Wiederkehrenden Termin einrichten
Die Methoden setTimeout()
oder setInterval()
werden häufig für verzögerte oder periodische Aufgaben verwendet. Diese APIs können jedoch fehlschlagen, da der Scheduler die Timer abbricht, wenn der Dienst-Worker beendet wird. Stattdessen können Erweiterungen die chrome.alarms
API verwenden.
Fordern Sie zuerst die Berechtigung "alarms"
im Manifest an. Wenn Sie die Tipps zur Erweiterung von einem Remote-Speicherort abrufen möchten, müssen Sie außerdem die Hostberechtigung anfordern:
manifest.json:
{
...
"permissions": ["storage"],
"permissions": ["storage", "alarms"],
"host_permissions": ["https://chrome.dev/f/*"],
}
Die Erweiterung ruft alle Tipps ab, wählt einen zufällig aus und speichert ihn im Speicher. Wir erstellen einen Wecker, der einmal täglich ausgelöst wird, um den Tipp zu aktualisieren. Wecker werden nicht gespeichert, wenn Sie Chrome schließen. Wir müssen also prüfen, ob der Wecker vorhanden ist, und ihn erstellen, falls nicht.
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);
Schritt 7: Mit anderen Kontexten kommunizieren
Erweiterungen verwenden Content-Scripts, um den Inhalt der Seite zu lesen und zu ändern. Wenn ein Nutzer eine Chrome API-Referenzseite besucht, wird die Seite über das Inhaltsskript der Erweiterung mit dem Tipp des Tages aktualisiert. Es sendet eine Nachricht, um den Tipp des Tages vom Dienstarbeiter anzufordern.
Deklarieren Sie zuerst das Inhaltsskript im Manifest und fügen Sie das Abgleichmuster hinzu, das der Referenzdokumentation der Chrome API entspricht.
manifest.json:
{
...
"content_scripts": [
{
"matches": ["https://developer.chrome.com/docs/extensions/reference/*"],
"js": ["content.js"]
}
]
}
Erstellen Sie eine neue Inhaltsdatei. Im folgenden Code wird eine Nachricht an den Dienstarbeiter gesendet, in der der Tipp angefordert wird. Dann fügen Sie eine Schaltfläche hinzu, über die ein Pop-up mit dem Erweiterungshinweis geöffnet wird. In diesem Code wird die neue Webplattform Popover API verwendet.
content.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;
}
Im letzten Schritt fügen wir unserem Service Worker einen Nachrichten-Handler hinzu, der eine Antwort mit dem täglichen Tipp an das Inhaltsskript sendet.
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;
}
});
Funktion testen
Die Dateistruktur Ihres Projekts sollte so aussehen:
Erweiterung lokal laden
Wenn Sie eine entpackte Erweiterung im Entwicklermodus laden möchten, folgen Sie der Anleitung unter Hallo Welt.
Referenzseite öffnen
- Geben Sie das Keyword „api“ in die Adressleiste des Browsers ein.
- Drücken Sie die Tabulatortaste oder die Leertaste.
- Geben Sie den vollständigen Namen der API ein.
- ODER aus einer Liste früherer Suchanfragen auswählen
- Daraufhin wird die Chrome API-Referenzseite in einem neuen Tab geöffnet.
Das sollte so aussehen:
![Schnelle API-Referenz, die die Runtime API-Referenz öffnet](https://developer.chrome.google.cn/static/docs/extensions/get-started/tutorial/service-worker-events/image/quick-api-reference-openi-5041b3b640769.gif?authuser=4&hl=de)
Tipp des Tages öffnen
Klicken Sie in der Navigationsleiste auf die Schaltfläche „Tipp“, um den Tipp zur Erweiterung zu öffnen.
![Täglichen Tipp in](https://developer.chrome.google.cn/static/docs/extensions/get-started/tutorial/service-worker-events/image/open-daily-tip-676249a78de8e.gif?authuser=4&hl=de)
🎯 Potenzielle Verbesserungen
Versuchen Sie, anhand dessen, was Sie heute gelernt haben, eine der folgenden Aufgaben zu erledigen:
- Weitere Möglichkeiten zur Implementierung der Omnibox-Vorschläge
- Erstellen Sie ein eigenes modales Fenster, um den Erweiterungshinweis anzuzeigen.
- Öffnen Sie eine zusätzliche Seite zu den API-Referenzseiten für Web-Erweiterungen der MDN.
Viel Erfolg!
Herzlichen Glückwunsch zum Abschluss dieser Anleitung. 🎉 Sie können Ihre Fähigkeiten mit den folgenden Anleitungen für Anfänger weiter ausbauen:
Erweiterung | Lerninhalte |
---|---|
Lesezeit | Damit können Sie ein Element automatisch auf einer bestimmten Gruppe von Seiten einfügen. |
Tabs Manager | Erstellen eines Pop-ups zum Verwalten von Browser-Tabs |
Konzentrationsmodus | Code auf der aktuellen Seite ausführen, nachdem auf die Erweiterungsaktion geklickt wurde. |
Weiter erkunden
Weitere Informationen zu Dienst-Workern für Erweiterungen finden Sie in den folgenden Artikeln: