Samouczek przedstawiający pojęcia związane z usługami instancji roboczych rozszerzeń
Omówienie
Ten samouczek zawiera wprowadzenie do usług w rozszerzeniu Chrome. W ramach tego samouczka utworzysz rozszerzenie, które pozwoli użytkownikom szybko przechodzić do stron referencyjnych interfejsu API Chrome za pomocą paska wyszukiwania. Zapoznasz się z tymi zagadnieniami:
- Zarejestruj skrypt service worker i importuj moduły.
- Debugowanie rozszerzenia service workera.
- zarządzać stanem i obsługiwać zdarzenia.
- Wywoływanie okresowych zdarzeń.
- komunikować się ze skryptami treści;
Zanim rozpoczniesz
W tym przewodniku zakładamy, że masz podstawowe doświadczenie w programowaniu stron internetowych. Aby zapoznać się z ogólnymi informacjami na temat tworzenia rozszerzeń, przeczytaj artykuły Rozszerzenia 101 i Hello World.
Tworzenie rozszerzenia
Najpierw utwórz nowy katalog o nazwie quick-api-reference
, aby przechowywać pliki rozszerzeń, lub pobierz kod źródłowy z naszego repozytorium GitHub samples.
Krok 1. Zarejestruj usługę w tle
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ą swojego pracownika usługi w pliku manifestu, który zawiera tylko 1 plik JavaScript.
Nie musisz wywoływać funkcji navigator.serviceWorker.register()
, jak na stronie internetowej.
Utwórz folder images
, a potem pobierz do niego ikony.
Aby dowiedzieć się więcej o metadata i ikonach rozszerzenia w pliku manifestu, zapoznaj się z pierwszymi krokami samouczka Czas na czytanie.
Krok 2. Zaimportuj wiele modułów usług robota
Nasz serwis worker implementuje 2 funkcje. Aby ułatwić utrzymanie, każdą funkcję zaimplementujemy w osobnym module. Najpierw musimy zadeklarować w pliku manifestu usługę workera jako moduł ES, co pozwoli nam zaimportować moduły w usłudze workera:
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 log konsoli.
sw-omnibox.js:
console.log("sw-omnibox.js");
sw-tips.js:
console.log("sw-tips.js");
Aby dowiedzieć się, jak importować wiele plików w ramach usługi workera, zapoznaj się z artykułem Importowanie skryptów.
Opcjonalnie: debugowanie usługi workera
Wyjaśnię, jak znaleźć dzienniki usługi w ramach workera i jak sprawdzić, kiedy został on zakończony. Najpierw postępuj zgodnie z instrukcjami wczytywania rozpakowanego rozszerzenia.
Po 30 sekundach zobaczysz komunikat „service worker (inactive)” (element usługi nieaktywny), co oznacza, że element usługi został zamknięty. Kliknij link „Usługa (nieaktywna)”, aby go sprawdzić. Pokazuje to poniższa animacja.
Czy zauważyłeś/zauważyłaś, że skontrolowanie skryptu service worker spowodowało jego uruchomienie? Otwarcie service workera w narzędziach deweloperskich spowoduje, że pozostanie on aktywny. Aby mieć pewność, że rozszerzenie działa prawidłowo po zakończeniu działania usługi, pamiętaj o zamknięciu DevTools.
Teraz rozłóż rozszerzenie, aby dowiedzieć się, gdzie szukać błędów. Jednym ze sposobów jest usunięcie rozszerzenia „.js” z importu './sw-omnibox.js'
w pliku service-worker.js
. Chrome nie będzie mógł 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 rozszerzenia service worker znajdziesz w artykule Debugowanie rozszerzeń.
Krok 4. Inicjalizacja stanu
Jeśli nie są potrzebne, Chrome je wyłączy. Do zachowania stanu w sesjach usług w ramach interfejsu chrome.storage
. 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ć podczas pierwszego instalowania rozszerzenia, nasłuchując zdarzenia runtime.onInstalled()
:
sw-omnibox.js:
...
// Save default API suggestions
chrome.runtime.onInstalled.addListener(({ reason }) => {
if (reason === 'install') {
chrome.storage.local.set({
apiSuggestions: ['tabs', 'storage', 'scripting']
});
}
});
Serwisy nie mają bezpośredniego dostępu do obiektu window, więc nie mogą używać window.localStorage
do przechowywania wartości. Ponadto roboty usługowe to krótkotrwałe środowiska wykonawcze. Są one wielokrotnie zamykane w trakcie sesji przeglądarki użytkownika, co powoduje ich niezgodność z użyciem zmiennych globalnych. Zamiast tego użyj funkcji chrome.storage.local
, która przechowuje dane na komputerze lokalnym.
Aby dowiedzieć się więcej o innych opcjach przechowywania danych dla pracowników usługi w rozszerzeniu, przeczytaj artykuł Zachowuj dane zamiast używać zmiennych globalnych.
Krok 5. Zarejestruj zdarzenia
Wszystkie odbiorniki zdarzeń muszą być zarejestrowane statycznie w zakresie globalnym usługi. Innymi słowy, odbiorniki zdarzeń nie powinny być zagnieżdżane w funkcjach asynchronicznych. Dzięki temu Chrome może zapewnić przywrócenie wszystkich przetwarzaczy zdarzeń w przypadku ponownego uruchomienia usługi.
W tym przykładzie użyjemy interfejsu API chrome.omnibox
, ale najpierw musimy zadeklarować w pliku manifestu aktywator słowa kluczowego w polu wyszukiwania:
manifest.json:
{
...
"minimum_chrome_version": "102",
"omnibox": {
"keyword": "api"
},
}
Teraz zarejestruj detektory zdarzeń w omniboksie na najwyższym poziomie skryptu. Gdy użytkownik wpisze słowo kluczowe w omniboksie (api
) na pasku adresu, a następnie tabulator lub spację, Chrome wyświetli listę sugestii na podstawie przechowywanych słów kluczowych. 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
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);
});
Gdy użytkownik wybierze sugestię, onInputEntered()
otworzy odpowiednią stronę dokumentacji interfejsu API Chrome.
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);
});
Funkcja updateHistory()
pobiera dane z omniboxa i zapisuje je w storage.local
. Dzięki temu ostatnio użyte hasło może zostać później użyte jako sugestia w omniboksie.
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 });
}
Krok 6. Skonfiguruj wydarzenie cykliczne
Metody setTimeout()
lub setInterval()
są często używane do wykonywania opóźnionych lub okresowych zadań. Te interfejsy API mogą jednak nie działać, ponieważ po zakończeniu działania usługi harmonogram anuluje zegary. Zamiast tego rozszerzenia mogą używać interfejsu API chrome.alarms
.
Zacznij od zgłoszenia żądania uprawnienia "alarms"
w pliku manifestu. Aby pobrać wskazówki dotyczące rozszerzenia z hostowanej lokalizacji zdalnej, musisz poprosić o uprawnienia dotyczące hosta:
manifest.json:
{
...
"permissions": ["storage"],
"permissions": ["storage", "alarms"],
"host_permissions": ["https://chrome.dev/f/*"],
}
Rozszerzenie pobierze wszystkie wskazówki, wybierze jedną losowo i zapisze ją w pamięci. Utworzymy alarm, który będzie uruchamiany raz dziennie w celu zaktualizowania wskazówki. Alarmy nie są zapisywane po zamknięciu Chrome. Musimy 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 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);
Krok 7. Komunikowanie się z innymi kontekstami
Rozszerzenia używają skryptów treści do odczytywania i modyfikowania zawartości strony. Gdy użytkownik otworzy stronę referencyjną interfejsu API Chrome, skrypt treści rozszerzenia zaktualizuje stronę o poradę dnia. Wysyła wiadomość z prośbą o podanie wskazówki dnia do usługi.
Najpierw zadeklaruj skrypt treści w pliku manifestu i dodaj wzór dopasowania zgodny z dokumentacją referencyjną 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 wiadomość do usługi, prosząc o wskazanie. Następnie dodaj przycisk, który otworzy wyskakujące okienko z poradami dotyczącymi rozszerzenia. Ten kod korzysta z nowego interfejsu Popover API na platformie internetowej.
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;
}
Ostatnim krokiem jest dodanie do naszego serwisu workera, który wysyła odpowiedź na skrypt treści z poradami na dany dzień.
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;
}
});
Sprawdzanie działania
Sprawdź, czy struktura plików projektu wygląda tak:
Ładowanie 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 wybrać z listy poprzednich wyszukiwań.
- Otworzy się nowa strona z dokumentacją interfejsu API Chrome.
Powinien on wyglądać podobnie do tego:
![Szybka dokumentacja interfejsu API otwierająca dokumentację interfejsu API w czasie wykonywania](https://developer.chrome.google.cn/static/docs/extensions/get-started/tutorial/service-worker-events/image/quick-api-reference-openi-5041b3b640769.gif?authuser=6&hl=pl)
Otwieranie wskazówki dnia
Aby otworzyć wskazówkę dotyczącą rozszerzenia, kliknij przycisk Wskazówka w panelu nawigacyjnym.
![Otwieranie codziennych wskazówek](https://developer.chrome.google.cn/static/docs/extensions/get-started/tutorial/service-worker-events/image/open-daily-tip-676249a78de8e.gif?authuser=6&hl=pl)
🎯 Możliwe ulepszenia
Na podstawie tego, czego się nauczyłeś(-aś) dzisiaj, spróbuj wykonać jedną z tych czynności:
- Poznaj inny sposób implementowania sugestii w polu wyszukiwania.
- Utwórz własny modal do wyświetlania wskazówki dotyczącej rozszerzenia.
- Otwórz dodatkową stronę na stronach referencyjnych interfejsu API rozszerzeń internetowych MDN.
Nie przestawaj tworzyć.
Gratulujemy ukończenia tego samouczka. 🎉 Aby dalej rozwijać swoje umiejętności, ukończ inne samouczki dla początkujących:
Rozszerzenie | Czego się nauczysz |
---|---|
Czas czytania | Aby automatycznie wstawić element na określonym zestawie stron. |
Menedżer kart | Aby utworzyć wyskakujące okienko do zarządzania 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ę edukacyjną dla pracowników obsługi klienta, przeczytaj te artykuły: