Service Worker'larla etkinlikleri işleme

Uzantı hizmet çalışanı kavramlarının ele alındığı eğitim

Genel bakış

Bu eğiticide, Chrome Uzantısı hizmet çalışanları hakkında temel bilgiler verilmiştir. Bu eğiticinin bir parçası olarak, kullanıcıların çok amaçlı adres çubuğunu kullanarak Chrome API referans sayfalarına hızlı bir şekilde gitmelerini sağlayan bir uzantı oluşturacaksınız. Bu derslere katılarak şunları öğreneceksiniz:

  • Service Worker'ınızı ve içe aktarma modüllerini kaydedin.
  • Uzantı hizmeti çalışanınızda hata ayıklayın.
  • Durumu yönetme ve etkinlikleri işleme.
  • Periyodik olayları tetikleyin.
  • İçerik komut dosyalarıyla iletişim kurma.

Başlamadan önce

Bu kılavuzda temel web geliştirme deneyiminiz olduğu varsayılır. Uzantı geliştirmeye giriş için Uzantılar 101 ve Hello World sayfalarını incelemenizi öneririz.

Uzantıyı oluşturun

Uzantı dosyalarını barındırmak için quick-api-reference adında yeni bir dizin oluşturarak başlayın veya GitHub örnekleri depomuzdan kaynak kodunu indirin.

1. Adım: Hizmet çalışanını kaydedin

Projenin kök dizininde manifest dosyasını oluşturun ve aşağıdaki kodu ekleyin:

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",
  },
}

Uzantılar, hizmet çalışanlarını yalnızca tek bir JavaScript dosyası alan manifeste kaydeder. Bir web sayfasında olduğu gibi navigator.serviceWorker.register() yöntemini çağırmanıza gerek yoktur.

Bir images klasörü oluşturup simgeleri indirin.

Manifest'te uzantının meta verileri ve simgeleri hakkında daha fazla bilgi edinmek için Okuma süresi eğiticisinin ilk adımlarına göz atın.

2. Adım: Birden fazla Service Worker modülünü içe aktarın

Hizmet çalışanımız iki özellik uygular. Daha iyi sürdürülebilirlik için her bir özelliği ayrı bir modülde uygulayacağız. Öncelikle Service Worker'ı manifest dosyamızda bir ES Modülü olarak beyan etmemiz gerekir. Bu modül, Service Worker'daki modülleri içe aktarmamıza olanak tanır:

manifest.json:

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

service-worker.js dosyasını oluşturun ve iki modülü içe aktarın:

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

Bu dosyaları oluşturun ve her birine bir konsol günlüğü ekleyin.

sw-omnibox.js:

console.log("sw-omnibox.js")

sw-tips.js:

console.log("sw-tips.js")

Bir hizmet çalışanında birden fazla dosyayı içe aktarmanın diğer yolları hakkında bilgi edinmek için Komut dosyalarını içe aktarma bölümüne bakın.

İsteğe bağlı: Hizmet çalışanında hata ayıklama

Service Worker günlüklerinin nasıl bulunacağını ve ne zaman sonlandırıldığını nasıl öğreneceğinizi açıklayacağım. İlk olarak Paketlenmemiş bir uzantı yükleme talimatlarını uygulayın.

30 saniye sonra "Service Worker (etkin değil)" ifadesini görürsünüz. Bu, hizmet çalışanının sonlandırıldığı anlamına gelir. İncelemek için "Service Worker (etkin değil)" bağlantısını tıklayın. Aşağıdaki animasyonda bu durum gösterilmektedir.

Service Worker'ı incelediğinizde uyanık olduğunu mu fark ettiniz? Hizmet çalışanı geliştirici araçlarında açıldığında etkin kalır. Hizmet çalışanınız sonlandırıldığında uzantınızın doğru davrandığından emin olmak için Geliştirici Araçları'nı kapatmayı unutmayın.

Şimdi hataları nerede bulacağınızı öğrenmek için uzantıyı kaldırın. Bunu yapmanın bir yolu, service-worker.js dosyasındaki './sw-omnibox.js' içe aktarma işleminden ".js" öğesini silmektir. Chrome, hizmet çalışanını kaydedemez.

chrome://extensions sayfasına geri dönün ve uzantıyı yenileyin. İki hata görürsünüz:

Service worker registration failed. Status code: 3.

An unknown error occurred when fetching the script.

Uzantı hizmeti çalışanında hata ayıklamayla ilgili daha fazla yöntem için Uzantılarda hata ayıklama bölümünü inceleyin.

4. Adım: Durumu başlatın

Chrome, ihtiyaç duyulmayan Service Worker'ları kapatır. Hizmet çalışanı oturumları genelinde durumu korumak için chrome.storage API'yi kullanırız. Depolama alanına erişim için manifest dosyasında izin istememiz gerekir:

manifest.json:

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

Öncelikle, varsayılan önerileri depolama alanına kaydedin. runtime.onInstalled() etkinliğini dinleyerek uzantının ilk kez yüklendiği durumu başlatabiliriz:

sw-omnibox.js:

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

Service Worker'lar window nesnesine doğrudan erişim sahibi değildir ve bu nedenle değerleri depolamak için window.localStorage öğesini kullanamaz. Ayrıca Service Worker'lar kısa ömürlü yürütme ortamlarıdır. Kullanıcının tarayıcı oturumu boyunca sürekli olarak sonlandırılırlar. Bu da genel değişkenlerle uyumsuzluğa neden olur. Bunun yerine, verileri yerel makinede depolayan chrome.storage.local aracını kullanın.

Uzantı hizmeti çalışanlarının diğer depolama alanı seçenekleri hakkında bilgi edinmek için Genel değişkenler kullanmak yerine verileri koruma başlıklı makaleyi inceleyin.

5. Adım: Etkinliklerinizi kaydedin

Tüm etkinlik işleyicilerin, hizmet çalışanının genel kapsamında statik olarak kayıtlı olması gerekir. Başka bir deyişle, etkinlik işleyiciler eşzamansız işlevlere yerleştirilmemelidir. Bu şekilde Chrome, Service Worker'ın yeniden başlatılması durumunda tüm etkinlik işleyicilerin geri yüklenmesini sağlayabilir.

Bu örnekte chrome.omnibox API'yi kullanacağız ancak önce çok amaçlı adres çubuğu anahtar kelime tetikleyicisini manifest dosyasında beyan etmemiz gerekmektedir:

manifest.json:

{
  ...
  "minimum_chrome_version": "102",
  "omnibox": {
    "keyword": "api"
  },
}

Şimdi çok amaçlı adres çubuğu etkinlik işleyicilerini komut dosyasının en üst düzeyine kaydedin. Kullanıcı adres çubuğuna çok amaçlı adres çubuğu anahtar kelimesini (api) ve ardından sekme veya boşluk yazdığında, Chrome, depolama alanındaki anahtar kelimelere dayalı bir öneri listesi görüntüler. Bu önerilerin doldurulması, geçerli kullanıcı girişini ve bir suggestResult nesnesini alan onInputChanged() etkinliğinden sorumludur.

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);
});

Kullanıcı bir öneriyi seçtikten sonra onInputEntered() ilgili Chrome API referans sayfasını açar.

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);
});

updateHistory() işlevi, çok amaçlı adres çubuğu girişini alır ve storage.local içine kaydeder. Böylece, en son arama terimi daha sonra çok amaçlı adres çubuğu önerisi olarak kullanılabilir.

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 });
}

6. Adım: Düzenli bir etkinlik oluşturun

setTimeout() veya setInterval() yöntemleri genellikle gecikmeli veya periyodik görevleri gerçekleştirmek için kullanılır. Ancak bu API'ler, hizmet çalışanı sonlandırıldığında planlayıcının zamanlayıcıları iptal etmesi nedeniyle başarısız olabilir. Uzantılar bunun yerine chrome.alarms API'yi kullanabilir.

Manifest dosyasında "alarms" iznini isteyerek başlayın. Ayrıca, uzantı ipuçlarını uzaktan barındırılan bir konumdan almak için barındırıcı izni istemeniz gerekir:

manifest.json:

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

Uzantı tüm ipuçlarını getirir, rastgele birini seçer ve depolama alanına kaydeder. İpucunu güncellemek için günde bir kez tetiklenecek bir alarm oluştururuz. Chrome'u kapattığınızda alarmlar kaydedilmez. Bu yüzden, alarmın var olup olmadığını kontrol etmemiz, yoksa oluşturmamız gerekir.

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);

7. Adım: Diğer bağlamlarla iletişim kurma

Uzantılar, sayfanın içeriğini okumak ve değiştirmek için içerik komut dosyalarını kullanır. Bir kullanıcı bir Chrome API referans sayfasını ziyaret ettiğinde, uzantının içerik komut dosyası sayfayı günün ipucuyla günceller. Hizmet çalışanından günün ipucunu istemek için bir mesaj gönderir.

Manifest'teki içerik komut dosyasını tanımlayarak başlayın ve Chrome API referans dokümanlarına karşılık gelen eşleşme kalıbını ekleyin.

manifest.json:

{
  ...
  "content_scripts": [
    {
      "matches": ["https://developer.chrome.com/docs/extensions/reference/*"],
      "js": ["content.js"]
    }
  ]
}

Yeni bir içerik dosyası oluşturun. Aşağıdaki kod, hizmet çalışanına bahşiş isteğinde bulunan bir mesaj gönderir. Ardından, uzantı ipucunu içeren bir pop-up penceresi açacak bir düğme ekler. Bu kod, yeni web platformu Popover API'sini kullanır.

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;
}

Son adım, hizmet çalışanlarımıza günlük ipucuyla içerik komut dosyasına yanıt gönderen bir mesaj işleyici eklemektir.

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;
  }
});

İşe yarayıp yaramadığını test etme

Projenizin dosya yapısının aşağıdaki gibi olduğunu doğrulayın:

Uzantı klasörünün içeriği: resimler klasörü, manifest.json, service-worker.js, sw-omnibox.js, sw-tips.js ve content.js

Uzantınızı yerel olarak yükleme

Geliştirici modunda paketlenmemiş bir uzantıyı yüklemek için Merhaba dünya bölümündeki adımları uygulayın.

Referans sayfası açma

  1. Tarayıcı adres çubuğuna "api" anahtar kelimesini girin.
  2. "Sekme" veya "boşluk" tuşuna basın.
  3. API'nin tam adını girin.
    • VEYA geçmiş aramalar listesinden seçim yapın
  4. Chrome API referans sayfası, yeni bir sayfa açılır.

Aşağıdaki gibi görünmelidir:

Çalışma zamanı API referansını açan Quick API Referansı
Runtime API'yi açan Quick API uzantısı.

Günün ipucunu aç

Uzantı ipucunu açmak için gezinme çubuğunda bulunan İpucu düğmesini tıklayın.

Günlük ipucunu şurada aç:
Quick API uzantısı, günün ipucunu açıyor.

🎯 Olası geliştirmeler

Bugün öğrendiklerinizi temel alarak aşağıdakilerden herhangi birini gerçekleştirmeyi deneyin:

  • Çok amaçlı adres çubuğu önerilerini uygulamanın başka bir yolunu keşfedin.
  • Uzantı ipucunu görüntülemek için kendi özel modelinizi oluşturun.
  • MDN'nin Web Extensions referans API'si sayfalarına ait bir ek sayfa açın.

Geliştirmeye devam edin!

Tebrikler, bu eğitimi tamamladınız 🎉. Yeni başlayanlara yönelik diğer eğiticileri tamamlayarak becerilerinizi geliştirmeye devam edin:

Uzantı Öğrenecekleriniz
Okuma süresi Öğeleri belirli bir sayfa grubuna otomatik olarak ekleme.
Sekme Yöneticisi Tarayıcı sekmelerini yöneten bir pop-up oluşturmak için.
Konsantrasyon Modu Uzantı işlemini tıkladıktan sonra geçerli sayfada kod çalıştırmak için.

Keşfetmeye devam edin

Uzantı hizmet çalışanı öğrenme rotanıza devam etmek için aşağıdaki makaleleri incelemenizi öneririz: