Progresyviųjų žiniatinklio programėlių architektūra: „JavaScript Service Worker“ modeliai | MLOG | MLOG

4. Tik tinklas (Network-Only)

Strategija „tik tinklas“ visada gauna išteklius iš tinklo, visiškai apeinant podėlį. Ši strategija naudojama, kai jums absoliučiai reikalinga naujausia ištekliaus versija ir podėlys nėra pageidaujamas.

Pavyzdys:

            
self.addEventListener('fetch', event => {
  event.respondWith(
    fetch(event.request)
  );
});

            

5. Pasenęs, kol tikrinama (Stale-While-Revalidate)

Strategija „pasenęs, kol tikrinama“ nedelsiant pateikia podėlyje esantį išteklių, tuo pačiu metu gaunant naujausią versiją iš tinklo. Kai tinklo užklausa baigiama, podėlys atnaujinamas nauja versija. Ši strategija užtikrina greitą pradinį atsakymą, kartu garantuojant, kad vartotojas galiausiai gaus naujausią turinį. Tai naudinga strategija nekritiniam turiniui, kuriam greitis yra svarbesnis už absoliutų naujumą.

Pavyzdys:

            
self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request)
      .then(response => {
        const fetchPromise = fetch(event.request).then(networkResponse => {
          caches.open('my-cache').then(cache => {
            cache.put(event.request, networkResponse.clone());
            return networkResponse;
          });
        });
        return response || fetchPromise;
      })
  );
});

            

6. Podėlis, tada tinklas (Cache, then Network)

Panaši į „pasenęs, kol tikrinama“, bet be greito podėlyje esančio ištekliaus grąžinimo. Pirmiausia patikrinamas podėlis, ir tik jei išteklius yra, tinklo užklausa tęsiama fone, kad būtų atnaujintas podėlis.

Tinkamos podėlio strategijos pasirinkimas

Optimali podėlio strategija priklauso nuo konkrečių jūsų programėlės reikalavimų. Atsižvelkite į tokius veiksnius kaip:

Atidžiai pasirinkdami tinkamas podėlio strategijas, galite žymiai pagerinti savo PWA našumą ir vartotojo patirtį, net ir neprisijungus. Įrankiai, tokie kaip „Workbox“ ([https://developers.google.com/web/tools/workbox](https://developers.google.com/web/tools/workbox)), gali supaprastinti šių strategijų įgyvendinimą.

Foninis sinchronizavimas: neprisijungus atliktų pakeitimų valdymas

Foninis sinchronizavimas leidžia jūsų PWA atlikti užduotis fone, net kai vartotojas yra neprisijungęs. Tai ypač naudinga tvarkant formų pateikimus, duomenų atnaujinimus ir kitas operacijas, kurioms reikalingas tinklo ryšys. `BackgroundSyncManager` API leidžia registruoti užduotis, kurios bus vykdomos, kai atsiras tinklo ryšys.

Foninio sinchronizavimo užduoties registravimas

Norėdami užregistruoti foninio sinchronizavimo užduotį, turite naudoti `register` metodą iš `BackgroundSyncManager`. Šis metodas kaip argumentą priima unikalų žymės pavadinimą. Žymės pavadinimas identifikuoja konkrečią užduotį, kurią reikia atlikti.

Pavyzdys:

            
self.addEventListener('sync', event => {
  if (event.tag === 'my-sync-task') {
    event.waitUntil(doSomeWork());
  }
});

            

Sinchronizavimo įvykio (sync event) tvarkymas

Kai naršyklė aptinka tinklo ryšį, ji išsiunčia `sync` įvykį „service worker“. Galite klausytis šio įvykio ir atlikti reikiamus veiksmus, pavyzdžiui, siųsti duomenis į serverį.

Pavyzdys:

            
async function doSomeWork() {
  // Retrieve data from IndexedDB
  const data = await getDataFromIndexedDB();

  // Send data to the server
  try {
    const response = await fetch('/api/sync', {
      method: 'POST',
      body: JSON.stringify(data),
      headers: {
        'Content-Type': 'application/json'
      }
    });

    if (response.ok) {
      // Clear the data from IndexedDB
      await clearDataFromIndexedDB();
    } else {
      // Handle errors
      console.error('Sync failed:', response.status);
      throw new Error('Sync failed');
    }
  } catch (error) {
    // Handle network errors
    console.error('Network error:', error);
    throw error;
  }
}

            

Pavyzdys: formos pateikimas neprisijungus

Įsivaizduokite scenarijų, kai vartotojas užpildo formą būdamas neprisijungęs. „Service worker“ gali išsaugoti formos duomenis „IndexedDB“ ir užregistruoti foninio sinchronizavimo užduotį. Kai atsiras tinklo ryšys, „service worker“ paims formos duomenis iš „IndexedDB“ ir pateiks juos serveriui.

  1. Vartotojas užpildo formą ir paspaudžia pateikti būdamas neprisijungęs.
  2. Formos duomenys išsaugomi „IndexedDB“.
  3. Užregistruojama foninio sinchronizavimo užduotis su unikalia žyme (pvz., `form-submission`).
  4. Kai atsiranda tinklo ryšys, sužadinamas `sync` įvykis.
  5. „Service worker“ paima formos duomenis iš „IndexedDB“ ir pateikia juos serveriui.
  6. Jei pateikimas sėkmingas, formos duomenys pašalinami iš „IndexedDB“.

Tiesioginiai pranešimai: vartotojų įtraukimas laiku siunčiamais atnaujinimais

Tiesioginiai pranešimai (push notifications) leidžia jūsų PWA siųsti laiku siunčiamus atnaujinimus ir pranešimus vartotojams, net kai programėlė nėra aktyviai paleista naršyklėje. Tai gali žymiai pagerinti vartotojų įsitraukimą ir išlaikymą. „Push API“ ir „Notifications API“ veikia kartu, kad pateiktų tiesioginius pranešimus.

Tiesioginių pranešimų prenumerata

Norėdami gauti tiesioginius pranešimus, vartotojai pirmiausia turi suteikti leidimą jūsų PWA. Galite naudoti `PushManager` API, kad prenumeruotumėte vartotojus tiesioginiams pranešimams.

Pavyzdys:

            
navigator.serviceWorker.ready.then(registration => {
  registration.pushManager.subscribe({
    userVisibleOnly: true,
    applicationServerKey: 'YOUR_PUBLIC_VAPID_KEY'
  })
  .then(subscription => {
    // Send subscription details to your server
    sendSubscriptionToServer(subscription);
  })
  .catch(error => {
    console.error('Failed to subscribe:', error);
  });
});

            

Svarbu: Pakeiskite `YOUR_PUBLIC_VAPID_KEY` savo tikruoju VAPID (Voluntary Application Server Identification) raktu. VAPID raktai naudojami jūsų programų serveriui identifikuoti ir užtikrinti, kad tiesioginiai pranešimai būtų siunčiami saugiai.

Tiesioginių pranešimų tvarkymas

Gavus tiesioginį pranešimą, „service worker“ išsiunčia `push` įvykį. Galite klausytis šio įvykio ir parodyti pranešimą vartotojui.

Pavyzdys:

            
self.addEventListener('push', event => {
  const payload = event.data ? event.data.text() : 'No payload';

  event.waitUntil(
    self.registration.showNotification('My PWA', {
      body: payload,
      icon: 'icon.png'
    })
  );
});

            

Tiesioginių pranešimų pritaikymas

„Notifications API“ leidžia pritaikyti tiesioginių pranešimų išvaizdą ir elgseną. Galite nurodyti pavadinimą, tekstą, piktogramą, ženklelį ir kitas parinktis.

Pavyzdys:

            
self.addEventListener('push', event => {
  const data = event.data.json();
  const title = data.title || 'My PWA';
  const options = {
    body: data.body || 'No message',
    icon: data.icon || 'icon.png',
    badge: data.badge || 'badge.png',
    vibrate: [200, 100, 200],
    data: { // Custom data that you can access when the user clicks the notification
      url: data.url || '/'
    },
    actions: [
      {action: 'explore', title: 'Explore this new world',
        icon: 'images/checkmark.png'},
      {action: 'close', title: 'Close',
        icon: 'images/xmark.png'},
    ]
  };

  event.waitUntil(self.registration.showNotification(title, options));
});


self.addEventListener('notificationclick', function(event) {
  event.notification.close();

  // Check if the user clicked on an action.
  if (event.action === 'explore') {
    clients.openWindow(event.notification.data.url);
  } else {
    // Default action: open the app.
    clients.openWindow('/');
  }
});

            

Pavyzdys: naujienų pranešimas

Naujienų programėlė gali naudoti tiesioginius pranešimus, kad įspėtų vartotojus apie svarbiausias naujienas. Paskelbus naują straipsnį, serveris siunčia tiesioginį pranešimą į vartotojo įrenginį, kuriame rodoma trumpa straipsnio santrauka. Tada vartotojas gali spustelėti pranešimą, kad atidarytų visą straipsnį PWA.

Pažangūs „Service Worker“ modeliai

1. Analizė neprisijungus

Stebėkite vartotojų elgseną net tada, kai jie yra neprisijungę, saugodami analizės duomenis vietoje ir siųsdami juos į serverį, kai atsiranda tinklo ryšys. Tai galima pasiekti naudojant „IndexedDB“ ir foninį sinchronizavimą.

2. Versijavimas ir atnaujinimas

Įgyvendinkite patikimą „service worker“ versijavimo strategiją, kad užtikrintumėte, jog vartotojai visada gautų naujausius atnaujinimus, netrikdydami jų patirties. Naudokite podėlio anuliavimo (cache busting) metodus, kad anuliuotumėte senus podėlyje esančius išteklius.

3. Moduliniai „Service Workers“

Suskirstykite savo „service worker“ kodą į modulius, kad pagerintumėte jo priežiūrą ir skaitomumą. Naudokite „JavaScript“ modulius (ESM) arba modulių rišiklį, pvz., „Webpack“ ar „Rollup“.

4. Dinaminis podėlys

Išteklius į podėlį įkelkite dinamiškai, atsižvelgdami į vartotojo sąveikas ir naudojimo modelius. Tai gali padėti optimizuoti podėlio dydį ir pagerinti našumą.

Geriausios „Service Worker“ kūrimo praktikos

Išvada

„JavaScript service workers“ yra galingi įrankiai, skirti kurti patikimas, našias ir įtraukiančias PWA. Suprasdami „service worker“ gyvavimo ciklą ir įgyvendindami tinkamas podėlio strategijas, foninį sinchronizavimą ir tiesioginius pranešimus, galite sukurti išskirtinę vartotojo patirtį net ir neprisijungus. Šiame straipsnyje buvo nagrinėjami pagrindiniai „service worker“ modeliai ir geriausios praktikos, padėsiančios jums sėkmingai kurti PWA pasaulinei auditorijai. Žiniatinkliui toliau tobulėjant, „service workers“ vaidins vis svarbesnį vaidmenį formuojant žiniatinklio kūrimo ateitį.

Nepamirškite pritaikyti šių modelių pagal konkrečius savo programėlės reikalavimus ir visada teikite pirmenybę vartotojo patirčiai. Pasinaudodami „service workers“ galia, galite sukurti PWA, kurios yra ne tik funkcionalios, bet ir malonios naudoti, nepriklausomai nuo vartotojo buvimo vietos ar tinklo ryšio.

Papildomi ištekliai: