Servicemedewerkers en het applicatieshell-model

Een gemeenschappelijk architectonisch kenmerk van webapplicaties met één pagina (SPA) is een minimale set HTML, CSS en JavaScript die nodig is om de globale functionaliteit van een applicatie te ondersteunen. In de praktijk zijn dit meestal de koptekst, navigatie en andere algemene elementen van de gebruikersinterface die op alle pagina's aanwezig zijn. Wanneer een servicemedewerker de HTML van deze minimale gebruikersinterface en de bijbehorende assets vooraf in de cache plaatst, noemen we dit de applicatieshell .

Een diagram van een applicatieshell. Het is een screenshot van een webpagina met bovenaan een kop en onderaan een inhoudsgebied. De koptekst heeft het label 'Applicatie Shell', terwijl de onderkant het label 'Inhoud' heeft.

De applicatieshell speelt een belangrijke rol in de waargenomen prestaties van een webapplicatie. Het is het eerste dat wordt geladen en daarom is het ook het eerste dat gebruikers zien terwijl ze wachten tot de inhoud de gebruikersinterface vult.

Hoewel de applicatieshell snel kan worden geladen (op voorwaarde dat het netwerk beschikbaar en op zijn minst enigszins snel is), geeft een servicemedewerker die de applicatieshell en de bijbehorende assets vooraf in de cache plaatst, het applicatieshellmodel deze extra voordelen:

  • Betrouwbare, consistente prestaties bij herhaalde bezoeken. Bij het eerste bezoek aan een app zonder dat er een servicemedewerker is geïnstalleerd, moeten de markup van de applicatie en de bijbehorende assets uit het netwerk worden geladen voordat de servicemedewerker deze in de cache kan plaatsen. Bij herhaalde bezoeken wordt de applicatieshell echter uit de cache gehaald, wat betekent dat het laden en renderen onmiddellijk zal plaatsvinden.
  • Betrouwbare toegang tot functionaliteit in offline scenario's. Soms is de internettoegang onregelmatig of helemaal afwezig, en het gevreesde scherm 'we kunnen die website niet vinden' steekt de kop op. Het applicatieshell-model pakt dit aan door op elk navigatieverzoek te reageren met de applicatieshell-opmaak uit de cache. Zelfs als iemand een URL in uw web-app bezoekt waar hij of zij nog nooit eerder is geweest, wordt de applicatieshell bediend vanuit de cache en kan deze worden gevuld met nuttige inhoud.

Wanneer het applicatieshell-model moet worden gebruikt

Een applicatieshell is het meest zinvol als u gemeenschappelijke elementen van de gebruikersinterface hebt die niet van route tot route veranderen, maar de inhoud wel. De meeste SPA's gebruiken waarschijnlijk al een applicatieshell-model.

Als dit uw project beschrijft en u een servicemedewerker wilt toevoegen om de betrouwbaarheid en prestaties ervan te verbeteren, moet de applicatieshell:

  • Laad snel .
  • Gebruik statische assets uit een Cache instantie.
  • Voeg algemene interface-elementen toe, zoals een koptekst en zijbalk, los van de inhoud van de pagina.
  • Paginaspecifieke inhoud ophalen en weergeven.
  • Indien nodig kunt u dynamische inhoud eventueel in de cache opslaan voor offline weergave.

De applicatieshell laadt paginaspecifieke inhoud dynamisch via API's of inhoud gebundeld in JavaScript. Het zou ook zichzelf moeten bijwerken, in die zin dat als de markup van de applicatieshell verandert, een update van een servicemedewerker de nieuwe applicatieshell moet oppikken en deze automatisch in de cache moet opslaan.

Het bouwen van de applicatieshell

De applicatieshell moet onafhankelijk van de inhoud bestaan, maar toch een basis bieden voor de inhoud die erin kan worden gevuld. Idealiter zou het zo slank mogelijk moeten zijn, maar voldoende betekenisvolle inhoud moeten bevatten in de eerste download, zodat de gebruiker begrijpt dat een ervaring snel wordt geladen.

De juiste balans is afhankelijk van uw app. De applicatieshell voor de Trained To Thrill-app van Jake Archibald bevat een header met een vernieuwingsknop om nieuwe inhoud van Flickr op te halen.

Een screenshot van de Trained to Thrill-webapp in twee verschillende statussen. Links is alleen de in de cache opgeslagen applicatieshell zichtbaar, zonder dat er inhoud is ingevuld. Aan de rechterkant wordt de inhoud (een paar afbeeldingen van enkele treinen) dynamisch geladen in het inhoudsgebied van de applicatieshell.

De opmaak van de applicatieshell varieert van project tot project, maar hier is een voorbeeld van een index.html bestand dat de standaard van de applicatie biedt:

​​<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>
      Application Shell Example
    </title>
    <link rel="manifest" href="/manifest.json">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <link rel="stylesheet" type="text/css" href="styles/global.css">
  </head>
  <body>
    <header class="header">
      <!-- Application header -->
      <h1 class="header__title">Application Shell Example</h1>
    </header>

    <nav class="nav">
      <!-- Navigation items -->
    </nav>

    <main id="app">
      <!-- Where the application content populates -->
    </main>

    <div class="loader">
      <!-- Spinner/content placeholders -->
    </div>

    <!-- Critical application shell logic -->
    <script src="app.js"></script>

    <!-- Service worker registration script -->
    <script>
      if ('serviceWorker' in navigator) {
        // Register a service worker after the load event
        window.addEventListener('load', () => {
          navigator.serviceWorker.register('/sw.js');
        });
      }
    </script>
  </body>
</html>

Hoe u ook een applicatieshell voor uw project bouwt, deze moet de volgende kenmerken hebben:

  • De HTML moet duidelijk geïsoleerde gebieden bevatten voor individuele elementen van de gebruikersinterface. In het bovenstaande voorbeeld omvat dit de koptekst van de toepassing, de navigatie, het gebied met de hoofdinhoud en ruimte voor een laad-spinner die alleen verschijnt wanneer de inhoud wordt geladen.
  • Het initiële JavaScript en CSS dat voor de applicatieshell wordt geladen, moet minimaal zijn en alleen betrekking hebben op de functionaliteit van de applicatieshell zelf en niet op de inhoud. Dit zorgt ervoor dat de applicatie zijn shell zo snel mogelijk weergeeft en het hoofdthreadwerk minimaliseert totdat de inhoud verschijnt.
  • Een inline script dat een servicemedewerker registreert.

Zodra de applicatieshell is gebouwd, kunt u een servicemedewerker bouwen om zowel de applicatieshell als de bijbehorende assets in de cache op te slaan.

Het cachen van de applicatieshell

De applicatieshell en de vereiste assets moeten de servicemedewerker onmiddellijk tijdens de installatie vooraf in de cache plaatsen. Laten we, uitgaande van een applicatieshell zoals het bovenstaande voorbeeld, eens kijken hoe we dit zouden kunnen bereiken in een eenvoudig Workbox-voorbeeld met behulp van workbox-build :

// build-sw.js
import {generateSW} from 'workbox-build';

// Where the generated service worker will be written to:
const swDest = './dist/sw.js';

generateSW({
  swDest,
  globDirectory: './dist',
  globPatterns: [
    // The necessary CSS and JS for the app shell
    '**/*.js',
    '**/*.css',
    // The app shell itself
    'shell.html'
  ],
  // All navigations for URLs not precached will use this HTML
  navigateFallback: 'shell.html'
}).then(({count, size}) => {
  console.log(`Generated ${swDest}, which precaches ${count} assets totaling ${size} bytes.`);
});

Deze configuratie, opgeslagen in build-sw.js importeert de CSS en JavaScript van de app, inclusief het shell-opmaakbestand van de applicatie in shell.html . Het script wordt als volgt met Node uitgevoerd:

node build-sw.js

De gegenereerde servicemedewerker wordt geschreven naar ./dist/sw.js en zal het volgende bericht registreren als hij klaar is:

Generated ./dist/sw.js, which precaches 5 assets totaling 44375 bytes.

Wanneer de pagina wordt geladen, plaatst de servicemedewerker de shell-opmaak van de applicatie en de afhankelijkheden ervan vooraf in de cache:

Een screenshot van het netwerkpaneel in Chrome's DevTools met een lijst met items die zijn gedownload van het netwerk. Door de servicemedewerker vooraf in de cache opgeslagen activa worden onderscheiden van andere activa door een tandwiel links in de rij. Tijdens de installatie worden verschillende JavaScript- en CSS-bestanden door de servicemedewerker vooraf in de cache geplaatst.
De servicemedewerker slaat de afhankelijkheden van de applicatieshell vooraf op in de cache tijdens de installatie. De precachingverzoeken bevinden zich in de laatste twee rijen en het tandwielpictogram naast het verzoek geeft aan dat de servicemedewerker het verzoek heeft afgehandeld.

Het vooraf cachen van de HTML, CSS en JavaScript van uw applicatieshell is mogelijk in vrijwel elke workflow, inclusief projecten die gebruik maken van bundelaars. Naarmate u verder komt in de documentatie, leert u hoe u Workbox rechtstreeks kunt gebruiken om uw toolchain in te stellen en een servicemedewerker te bouwen die het beste werkt voor uw project, ongeacht of het een SPA is.

Conclusie

Het combineren van het applicatieshell-model met een servicemedewerker is geweldig voor offline caching, vooral als je de precaching-functionaliteit combineert met een netwerk-eerst, waarbij je terugvalt op de cachestrategie voor markup- of API-reacties. Het resultaat is een betrouwbaar snelle ervaring die uw applicatieshell bij herhaalde bezoeken onmiddellijk weergeeft, zelfs in offline omstandigheden.