Samouczek dotyczący koncepcji związanych ze skryptem service worker rozszerzenia
Przegląd
Ten samouczek zawiera wprowadzenie do procesów roboczych rozszerzeń Chrome. W ramach tego samouczka utworzysz rozszerzenie, które umożliwi użytkownikom szybkie przechodzenie do stron referencyjnych interfejsu Chrome API za pomocą paska adresu. Zapoznasz się z tymi zagadnieniami:
- Zarejestruj skrypt service worker i zaimportuj moduły.
- Debuguj skrypt service worker rozszerzenia.
- zarządzać stanem i obsługiwać zdarzenia,
- wywoływać okresowe zdarzenia;
- komunikować się ze skryptami treści,
Zanim rozpoczniesz
W tym przewodniku zakładamy, że masz podstawowe doświadczenie w tworzeniu stron internetowych. Zalecamy zapoznanie się z artykułami Rozszerzenia 101 i Hello World, aby poznać podstawy tworzenia rozszerzeń.
Tworzenie rozszerzenia
Zacznij od utworzenia nowego katalogu o nazwie quick-api-reference, w którym będą przechowywane pliki rozszerzenia, lub pobierz kod źródłowy z naszego repozytorium przykładowych plików GitHub.
Krok 1. Zarejestruj skrypt service worker
Utwórz plik manifest w katalogu głównym projektu i dodaj ten kod:
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"
}
}
Rozszerzenia rejestrują swój skrypt service worker w pliku manifestu, który zawiera tylko 1 plik JavaScript.
Nie musisz wywoływać funkcji navigator.serviceWorker.register(), jak w przypadku strony internetowej.
Utwórz folder images, a następnie pobierz do niego ikony.
Zapoznaj się z pierwszymi krokami samouczka dotyczącego czasu czytania, aby dowiedzieć się więcej o metadanych i ikonach rozszerzenia w pliku manifestu.
Krok 2. Zaimportuj wiele modułów skryptu service worker
Nasz skrypt service worker implementuje 2 funkcje. Aby ułatwić utrzymanie, każdą funkcję zaimplementujemy w osobnym module. Najpierw musimy zadeklarować w pliku manifestu, że nasz skrypt service worker jest modułem ES. Dzięki temu będziemy mogli importować moduły w naszym skrypcie service worker:
manifest.json:
{
"background": {
"service_worker": "service-worker.js",
"type": "module"
},
}
Utwórz plik service-worker.js i zaimportuj 2 moduły:
import './sw-omnibox.js';
import './sw-tips.js';
Utwórz te pliki i dodaj do każdego z nich dziennik konsoli.
sw-omnibox.js:
console.log("sw-omnibox.js");
sw-tips.js:
console.log("sw-tips.js");
Więcej informacji o innych sposobach importowania wielu plików w skrypcie service worker znajdziesz w artykule Importowanie skryptów.
Opcjonalnie: debugowanie skryptu service worker
Wyjaśnię, jak znaleźć logi skryptu service worker i kiedy się zakończy. Najpierw postępuj zgodnie z instrukcjami wczytywania rozpakowanego rozszerzenia.
Po 30 sekundach zobaczysz komunikat „service worker (inactive)”, co oznacza, że skrypt service worker został zakończony. Kliknij link „skrypt service worker (nieaktywny)”, aby go sprawdzić. Pokazuje to poniższa animacja.
Czy widzisz, że sprawdzenie skryptu service worker spowodowało jego wybudzenie? Otwarcie skryptu service worker w narzędziach deweloperskich spowoduje, że pozostanie on aktywny. Aby mieć pewność, że rozszerzenie działa prawidłowo po zakończeniu działania skryptu service worker, zamknij Narzędzia deweloperskie.
Teraz podziel rozszerzenie, aby dowiedzieć się, gdzie znajdują się błędy. Jednym ze sposobów jest usunięcie „.js” z importu './sw-omnibox.js' w pliku service-worker.js. Chrome nie będzie w stanie zarejestrować skryptu service worker.
Wróć na stronę chrome://extensions i odśwież rozszerzenie. Zobaczysz 2 błędy:
Service worker registration failed. Status code: 3.
An unknown error occurred when fetching the script.
Więcej sposobów debugowania skryptu service worker rozszerzenia znajdziesz w artykule Debugowanie rozszerzeń.
Krok 4. Zainicjuj stan
Chrome wyłącza procesy robocze, jeśli nie są potrzebne. Używamy interfejsu browser.storage API, aby zachowywać stan w sesjach skryptu service worker. Aby uzyskać dostęp do pamięci, musimy poprosić o uprawnienia w pliku manifestu:
manifest.json:
{
...
"permissions": ["storage"],
}
Najpierw zapisz domyślne sugestie w pamięci. Stan możemy zainicjować, gdy rozszerzenie zostanie zainstalowane po raz pierwszy, nasłuchując zdarzenia runtime.onInstalled():
sw-omnibox.js:
...
// Save default API suggestions
browser.runtime.onInstalled.addListener(({ reason }) => {
if (reason === 'install') {
browser.storage.local.set({
apiSuggestions: ['tabs', 'storage', 'scripting']
});
}
});
Service workerzy nie mają bezpośredniego dostępu do obiektu window, dlatego nie mogą używać window.localStorage do przechowywania wartości. Ponadto service worker to krótkotrwałe środowiska wykonawcze, które są wielokrotnie zamykane w trakcie sesji przeglądarki użytkownika, co sprawia, że są one niezgodne ze zmiennymi globalnymi. Zamiast tego używaj browser.storage.local, która przechowuje dane na urządzeniu lokalnym.
Więcej informacji o innych opcjach przechowywania danych w przypadku procesów roboczych usług rozszerzeń znajdziesz w artykule Przechowywanie danych zamiast używania zmiennych globalnych.
Krok 5. Zarejestruj zdarzenia
Wszystkie odbiorniki zdarzeń muszą być statycznie zarejestrowane w globalnym zakresie skryptu service worker. Innymi słowy, detektory zdarzeń nie powinny być zagnieżdżone w funkcjach asynchronicznych. Dzięki temu Chrome może mieć pewność, że w przypadku ponownego uruchomienia skryptu service worker wszystkie moduły obsługi zdarzeń zostaną przywrócone.
W tym przykładzie użyjemy interfejsu API browser.omnibox, ale najpierw musimy zadeklarować w pliku manifestu aktywator słowa kluczowego w omniboksie:
manifest.json:
{
...
"minimum_chrome_version": "102",
"omnibox": {
"keyword": "api"
},
}
Teraz zarejestruj detektory zdarzeń paska adresu u góry skryptu. Gdy użytkownik wpisze słowo kluczowe omniboksu (api) na pasku adresu, a następnie naciśnie Tab lub spację, Chrome wyświetli listę sugestii na podstawie słów kluczowych w pamięci. Za wypełnianie tych sugestii odpowiada zdarzenie onInputChanged(), które przyjmuje bieżące dane wejściowe użytkownika i obiekt suggestResult.
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
browser.omnibox.onInputChanged.addListener(async (input, suggest) => {
await browser.omnibox.setDefaultSuggestion({
description: 'Enter a Chrome API or choose from past searches'
});
const { apiSuggestions } = await browser.storage.local.get('apiSuggestions');
const suggestions = apiSuggestions.map((api) => {
return { content: api, description: `Open browser.${api} API` };
});
suggest(suggestions);
});
Gdy użytkownik wybierze sugestię, onInputEntered() otworzy odpowiednią stronę dokumentacji interfejsu Chrome API.
sw-omnibox.js:
...
// Open the reference page of the chosen API
browser.omnibox.onInputEntered.addListener((input) => {
browser.tabs.create({ url: URL_CHROME_EXTENSIONS_DOC + input });
// Save the latest keyword
updateHistory(input);
});
Funkcja updateHistory() pobiera dane wejściowe z paska adresu i zapisuje je w storage.local. Dzięki temu ostatnie wyszukiwane hasło będzie można później wykorzystać jako sugestię w omniboksie.
sw-omnibox.js:
...
async function updateHistory(input) {
const { apiSuggestions } = await browser.storage.local.get('apiSuggestions');
apiSuggestions.unshift(input);
apiSuggestions.splice(NUMBER_OF_PREVIOUS_SEARCHES);
return browser.storage.local.set({ apiSuggestions });
}
Krok 6. Skonfiguruj wydarzenie cykliczne
Metody setTimeout() i setInterval() są często używane do wykonywania opóźnionych lub okresowych zadań. Jednak te interfejsy API mogą nie działać, ponieważ harmonogram anuluje timery po zakończeniu działania service workera. Zamiast tego rozszerzenia mogą używać interfejsu browser.alarms API.
Zacznij od poproszenia o uprawnienie "alarms" w pliku manifestu:
manifest.json:
{
...
"permissions": ["storage"],
"permissions": ["storage", "alarms"],
}
Rozszerzenie pobierze wszystkie wskazówki, wybierze jedną losowo i zapisze ją w pamięci. Utworzymy alarm, który będzie włączać się raz dziennie, aby aktualizować wskazówkę. Alarmy nie są zapisywane po zamknięciu Chrome. Musimy więc sprawdzić, czy alarm istnieje, a jeśli nie, utworzyć go.
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 browser.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 browser.alarms.get(ALARM_NAME);
if (typeof alarm === 'undefined') {
browser.alarms.create(ALARM_NAME, {
delayInMinutes: 1,
periodInMinutes: 1440
});
updateTip();
}
}
createAlarm();
// Update tip once a day
browser.alarms.onAlarm.addListener(updateTip);
Krok 7. Komunikacja z innymi kontekstami
Rozszerzenia używają skryptów treści do odczytywania i modyfikowania zawartości strony. Gdy użytkownik odwiedzi stronę referencyjną interfejsu Chrome API, skrypt treści rozszerzenia zaktualizuje ją, wyświetlając wskazówkę dnia. Wysyła wiadomość z prośbą o wskazówkę dnia do skryptu service worker.
Zacznij od zadeklarowania skryptu treści w pliku manifestu i dodania wzorca dopasowania odpowiadającego dokumentacji referencyjnej interfejsu Chrome API.
manifest.json:
{
...
"content_scripts": [
{
"matches": ["https://developer.chrome.com/docs/extensions/reference/*"],
"js": ["content.js"]
}
]
}
Utwórz nowy plik treści. Ten kod wysyła do skryptu service worker wiadomość z prośbą o wskazówkę. Następnie dodaje przycisk, który otwiera wyskakujące okienko z wskazówką dotyczącą rozszerzenia. Ten kod korzysta z nowego interfejsu Popover API platformy internetowej.
content.js:
(async () => {
// Sends a message to the service worker and receives a tip in response
const { tip } = await browser.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;
}
Ostatnim krokiem jest dodanie do skryptu service worker funkcji obsługi wiadomości, która wysyła do skryptu treści odpowiedź z codzienną wskazówką.
sw-tips.js:
...
// Send tip to content script via messaging
browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.greeting === 'tip') {
browser.storage.local.get('tip').then(sendResponse);
return true;
}
});
Sprawdź, czy działa
Sprawdź, czy struktura plików projektu wygląda tak:

Wczytywanie rozszerzenia lokalnie
Aby załadować rozpakowane rozszerzenie w trybie programisty, wykonaj czynności opisane w artykule Hello world.
Otwieranie strony referencyjnej
- Na pasku adresu przeglądarki wpisz słowo kluczowe „api”.
- Naciśnij „Tab” lub „spację”.
- Wpisz pełną nazwę interfejsu API.
- LUB wybierz z listy poprzednich wyszukiwań.
- Otworzy się nowa strona z dokumentacją interfejsu Chrome API.
Powinien on wyglądać podobnie do tego:
Otwieranie wskazówki dnia
Kliknij przycisk Wskazówka na pasku nawigacyjnym, aby otworzyć wskazówkę dotyczącą rozszerzenia.
🎯 Potencjalne ulepszenia
Na podstawie zdobytej dziś wiedzy spróbuj wykonać dowolne z tych zadań:
- Poznaj inny sposób wdrażania sugestii z omniboksu.
- Utwórz własne okno modalne do wyświetlania wskazówki dotyczącej rozszerzenia.
- Otwórz dodatkową stronę z dokumentacją interfejsu API rozszerzeń do przeglądarki MDN.
Nie przestawaj budować!
Gratulujemy ukończenia tego samouczka 🎉. Rozwijaj dalej swoje umiejętności, korzystając z innych samouczków dla początkujących:
| Rozszerzenie | Czego się nauczysz |
|---|---|
| Czas czytania | Aby automatycznie wstawiać element na określonym zestawie stron. |
| Menedżer kart | Aby utworzyć wyskakujące okienko, które zarządza kartami przeglądarki. |
| Tryb pełnej koncentracji | Aby uruchomić kod na bieżącej stronie po kliknięciu działania rozszerzenia. |
Przeglądaj dalej
Aby kontynuować ścieżkę szkoleniową dotyczącą skryptów service worker rozszerzeń, zalecamy zapoznanie się z tymi artykułami: