Tutoriel sur les concepts de service worker d'extension
Présentation
Ce tutoriel présente les service workers d'extension Chrome. Dans le cadre de ce tutoriel, vous allez créer une extension qui permet aux utilisateurs d'accéder rapidement aux pages de documentation de référence de l'API Chrome à l'aide de l'omnibox. Vous allez apprendre à effectuer les tâches suivantes :
- Enregistrer votre service worker et importer des modules
- Déboguer votre service worker d'extension
- Gérer l'état et les événements
- Déclencher des événements périodiques
- Communiquer avec des scripts de contenu
Avant de commencer
Ce guide suppose que vous avez une expérience de base en développement Web. Nous vous recommandons de consulter les pages Extensions 101 et Hello World pour découvrir le développement d' extensions.
Créer l'extension
Commencez par créer un répertoire nommé quick-api-reference pour contenir les fichiers d’extension, ou
téléchargez le code source à partir de notre dépôt d’exemples GitHub.
Étape 1 : Enregistrer le service worker
Créez le fichier manifeste à la racine du projet et ajoutez le code suivant :
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"
}
}
Les extensions enregistrent leur service worker dans le fichier manifeste, qui ne contient qu'un seul fichier JavaScript.
Il n'est pas nécessaire d'appeler navigator.serviceWorker.register(), comme vous le feriez dans une page Web.
Créez un dossier images, puis téléchargez-y les icônes.
Consultez les premières étapes du tutoriel sur le temps de lecture pour en savoir plus sur les métadonnées et les icônes de l'extension dans le fichier manifeste.
Étape 2 : Importer plusieurs modules de service worker
Notre service worker implémente deux fonctionnalités. Pour une meilleure maintenabilité, nous allons implémenter chaque fonctionnalité dans un module distinct. Tout d'abord, nous devons déclarer le service worker en tant que module ES dans notre fichier manifeste, ce qui nous permet d'importer des modules dans notre service worker :
manifest.json:
{
"background": {
"service_worker": "service-worker.js",
"type": "module"
},
}
Créez le fichier service-worker.js et importez deux modules :
import './sw-omnibox.js';
import './sw-tips.js';
Créez ces fichiers et ajoutez un journal de la console à chacun d'eux.
sw-omnibox.js:
console.log("sw-omnibox.js");
sw-tips.js:
console.log("sw-tips.js");
Consultez la section Importer des scripts pour découvrir d'autres façons d'importer plusieurs fichiers dans un service worker.
Facultatif : Déboguer le service worker
Je vais vous expliquer comment trouver les journaux du service worker et savoir quand il a été arrêté. Tout d'abord, suivez les instructions pour charger une extension non empaquetée.
Au bout de 30 secondes, le message "service worker (inactive)" s'affiche, ce qui signifie que le service worker a été arrêté. Cliquez sur le lien "service worker (inactive)" pour l'inspecter. L'animation suivante illustre ce processus.
Avez-vous remarqué que l'inspection du service worker l'a réactivé ? L'ouverture du service worker dans les outils de développement le maintiendra actif. Pour vous assurer que votre extension se comporte correctement lorsque votre service worker est arrêté, n'oubliez pas de fermer les outils de développement.
Maintenant, cassez l'extension pour savoir où trouver les erreurs. Pour ce faire, supprimez ".js" de l'importation './sw-omnibox.js' dans le fichier service-worker.js. Chrome ne pourra pas enregistrer le service worker.
Revenez à chrome://extensions et actualisez l'extension. Deux erreurs s'affichent :
Service worker registration failed. Status code: 3.
An unknown error occurred when fetching the script.
Consultez la section Déboguer des extensions pour découvrir d'autres façons de déboguer le service worker d'extension.
Étape 4 : Initialiser l'état
Chrome arrête les service workers s'ils ne sont pas nécessaires. Nous utilisons l' chrome.storage API pour conserver l'état entre les sessions de service worker. Pour accéder au stockage, nous devons demander l'autorisation dans le fichier manifeste :
manifest.json:
{
...
"permissions": ["storage"],
}
Commencez par enregistrer les suggestions par défaut dans le stockage. Nous pouvons initialiser l'état lors de la première installation de l'extension en écoutant l'événement 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']
});
}
});
Les service workers n'ont pas d'accès direct à l'objet window et ne peuvent donc pas utiliser
window.localStorage pour stocker des valeurs. De plus, les service workers sont des environnements d'exécution de courte durée. Ils sont arrêtés à plusieurs reprises au cours d'une session de navigateur d'un utilisateur, ce qui les rend incompatibles avec les variables globales. Utilisez plutôt chrome.storage.local, qui stocke les données sur la machine locale.
Consultez la section Conserver les données plutôt que d'utiliser des variables globales pour en savoir plus sur les autres options de stockage pour les service workers d'extension.
Étape 5 : Enregistrer vos événements
Tous les écouteurs d'événements doivent être enregistrés de manière statique dans le champ d'application global du service worker. En d'autres termes, les écouteurs d'événements ne doivent pas être imbriqués dans des fonctions asynchrones. Ainsi, Chrome peut s'assurer que tous les gestionnaires d'événements sont restaurés en cas de redémarrage du service worker.
Dans cet exemple, nous allons utiliser l'API chrome.omnibox, mais nous devons d'abord déclarer le déclencheur de mot clé omnibox dans le fichier manifeste :
manifest.json:
{
...
"minimum_chrome_version": "102",
"omnibox": {
"keyword": "api"
},
}
Maintenant, enregistrez les écouteurs d'événements omnibox au niveau supérieur du script. Lorsque l'utilisateur saisit le mot clé omnibox (api) dans la barre d'adresse, suivi d'une tabulation ou d'un espace, Chrome affiche une liste de suggestions basées sur les mots clés stockés. L'événement onInputChanged(), qui prend l'entrée utilisateur actuelle et un objet suggestResult, est responsable du remplissage de ces suggestions.
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);
});
Une fois que l'utilisateur a sélectionné une suggestion, onInputEntered() ouvre la documentation de référence de l'API Chrome correspondante.
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);
});
La fonction updateHistory() prend l'entrée omnibox et l'enregistre dans storage.local. Ainsi, le terme de recherche le plus récent peut être utilisé ultérieurement comme suggestion omnibox.
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 });
}
Étape 6 : Configurer un événement périodique
Les méthodes setTimeout() ou setInterval() sont couramment utilisées pour effectuer des tâches différées ou périodiques. Toutefois, ces API peuvent échouer, car le planificateur annule les minuteurs lorsque le service worker est arrêté. Les extensions peuvent plutôt utiliser l'API chrome.alarms.
Commencez par demander l'autorisation "alarms" dans le fichier manifeste :
manifest.json:
{
...
"permissions": ["storage"],
"permissions": ["storage", "alarms"],
}
L'extension récupère tous les conseils, en choisit un au hasard et l'enregistre dans le stockage. Nous allons créer une alarme qui se déclenchera une fois par jour pour mettre à jour le conseil. Les alarmes ne sont pas enregistrées lorsque vous fermez Chrome. Nous devons donc vérifier si l'alarme existe et la créer si ce n'est pas le cas.
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);
Étape 7 : Communiquer avec d'autres contextes
Les extensions utilisent des scripts de contenu pour lire et modifier le contenu de la page. Lorsqu'un utilisateur consulte une documentation de référence de l'API Chrome, le script de contenu de l'extension met à jour la page avec le conseil du jour. Il envoie un message pour demander le conseil du jour au service worker.
Commencez par déclarer le script de contenu dans le fichier manifeste et ajoutez le modèle de correspondance correspondant à la documentation de référence de l'API Chrome.
manifest.json:
{
...
"content_scripts": [
{
"matches": ["https://developer.chrome.com/docs/extensions/reference/*"],
"js": ["content.js"]
}
]
}
Créez un fichier de contenu. Le code suivant envoie un message au service worker demandant le conseil. Ensuite, il ajoute un bouton qui ouvre une fenêtre pop-up contenant le conseil de l'extension. Ce code utilise la nouvelle API Popover de la plate-forme Web .
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;
}
La dernière étape consiste à ajouter un gestionnaire de messages à notre service worker qui envoie une réponse au script de contenu avec le conseil quotidien.
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;
}
});
Vérifier que tout fonctionne
Vérifiez que la structure de fichiers de votre projet ressemble à ce qui suit :

Charger votre extension en local
Pour charger une extension non empaquetée en mode développeur, suivez les étapes décrites dans Hello world.
Ouvrir une page de référence
- Saisissez le mot clé "api" dans la barre d'adresse du navigateur.
- Appuyez sur "Tabulation" ou "Espace".
- Saisissez le nom complet de l'API.
- OU choisissez une recherche précédente dans la liste.
- Une nouvelle page s'ouvre sur la documentation de référence de l'API Chrome.
Elle devrait se présenter comme ceci :
Ouvrir le conseil du jour
Cliquez sur le bouton "Conseil" situé dans la barre de navigation pour ouvrir le conseil de l'extension.
🎯 Améliorations potentielles
En fonction de ce que vous avez appris aujourd'hui, essayez d'effectuer l'une des opérations suivantes :
- Découvrez une autre façon d'implémenter les suggestions omnibox.
- Créez votre propre modal personnalisé pour afficher le conseil de l'extension.
- Ouvrez une page supplémentaire sur les pages de référence de l'API Web Extensions de MDN.
Continuez à créer !
Félicitations ! Vous avez terminé ce tutoriel 🎉. Continuez à améliorer vos compétences en suivant d'autres tutoriels pour débutants :
| Extension | Objectifs de l'atelier |
|---|---|
| Temps de lecture | Insérer automatiquement un élément sur un ensemble spécifique de pages. |
| Gestionnaire d'onglets | Créer une fenêtre pop-up qui gère les onglets du navigateur. |
| Mode Sans distractions | Exécuter du code sur la page actuelle après avoir cliqué sur l'action de l'extension. |
Continuer à explorer
Pour poursuivre votre parcours de formation sur les service workers d'extension, nous vous recommandons de consulter les articles suivants :