typescript - Angular PWA i mikrofrontend
Jeg har flere mikrofrontend-oppsett som bruker en "app-shell" type app for domenets rot og hver mikrofrontend på det første stielementet. Hver app er bygget som en frittstående Angular-applikasjon som bruker delte biblioteker for å gjenbruke vanlige komponenter og funksjonalitet. De ligger i sine egne separate Docker-containere og er bundet sammen ved hjelp av Nginx-proxykart.
mydomain.com/ <- domain root app
/child1 <- micro apps
/child2
/child3
/child4
Jeg vil sette opp en Angular service worker for å cache alle ressursene våre.
Første forsøk
Ha én service worker per app. Så domene-rot-appen hadde én, og hver av våre «barne-apper» hadde én. Det vil si; én ngsw-config.json per frittstående Angular-app.
Problem
Dette resulterte i at to SW-er kjempet om cache-kontroll i hver barneapp, og brukere kunne ende opp med å se en eldre versjon avhengig av hvilken som vant.
Andre forsøk
Ha én service worker som styrer alt, plasser den på domenets rot-app og la den forsøke å cache alle "child-app"s ressurser ved å bruke ngsw-config.json sine enten assetGroup.resources.files eller assetGroup.resources.urls. Ingen av disse ser ut til å mappe child-apps ressurser inn i cachen sin - i det minste ikke når man inspiserer DevTools AppCache-repositoriet, selv om nettverksfanen rapporterer at ressursfilen blir servert fra ServiceWorker. 🤔
Problem
Problemet her er at appene ikke lenger rapporterer når en ny versjon blir distribuert. Jeg antar at dette er fordi angular-cli ikke har noen måte å vite navnet på de kompilerte ressursene til barne-appene under bygging. De må caches under kjøring. Uansett er jeg ikke helt sikker på om noen av ressursene mine caches i det hele tatt. Ved å bytte til frakoblet modus, svarer ingenting.
Vi opplever også at en eldre versjon av domenets rot-app noen ganger lastes først, og vi må oppdatere siden for å få den oppdaterte versjonen. Jeg har injisert kode for å rydde opp den andre service-worker fra mitt første forsøk. Følgende kode fjerner alle service workere registrert til mydomain.com/childX:
// Force remove old redundant service workers
if ('serviceWorker' in navigator) {
navigator.serviceWorker.getRegistrations().then(registrations => {
registrations
.filter(r => 'scope' in r && r.scope !== `${location.protocol}//${location.host}/`)
.forEach(r => r.unregister());
});
}
En annen observasjon jeg ser er at i DevTools/Application/Cache storage, har jeg nøyaktig 4 oppføringer per ny versjon-hash, og den beholder alle versjoner. Jeg trodde den ville overskrive cachen når en ny versjon ble funnet.
Gjeldende oppsett:
Kjører @angular/service-worker: 10.1.4
ngsw-konfig.json
{
"$schema": "./node_modules/@angular/service-worker/config/schema.json",
"index": "/index.html",
"assetGroups": [
{
"name": "root",
"installMode": "prefetch",
"updateMode": "prefetch",
"resources": {
"files": [
"/assets/icons/favicon.ico",
"/index.html",
"/manifest.webmanifest",
"/*.css",
"/*.js",
"/*.txt"
]
}
},
{
"name": "apps",
"installMode": "lazy",
"updateMode": "prefetch",
"resources": {
"files": [
"/**/assets/icons/favicon.ico",
"/**/index.html",
"/**/manifest.webmanifest",
"/**/*.css",
"/**/*.js",
"/**/*.txt"
]
}
},
{
"name": "root-assets",
"installMode": "prefetch",
"updateMode": "prefetch",
"resources": {
"files": [
"/assets/**",
"/*.(eot|svg|cur|jpg|png|webp|gif|otf|ttf|woff|woff2|ani)"
]
}
},
{
"name": "apps-assets",
"installMode": "lazy",
"updateMode": "prefetch",
"resources": {
"files": [
"/**/assets/**",
"/**/*.(eot|svg|cur|jpg|png|webp|gif|otf|ttf|woff|woff2|ani)"
]
}
}
]
}
app.component.ts
constructor(updates: SwUpdate) {
// Make sure we run on an updated version
if (updates.isEnabled) {
// Ask user for permission to update once a new update is registered
updates.available.subscribe(() => {
if (confirm('A newer version of the application is available. Load the new version?')) {
updates.activateUpdate().then(() => document.location.reload());
}
});
// Check every 5 minutes for updates
timer(0, 5 * 60 * 1000).subscribe(n => updates.checkForUpdate());
} else {
console.log('SW not enabled!');
}
}
Spørsmål
Hvordan bør dette konfigureres for at serviceworkeren(e) skal kunne cache ressursene mine riktig, og (hvis det kreves én per app) ikke motarbeide hverandre?
REDIGER
For andre som sliter med dette problemet; Muligens kan dette løses ved å bruke det nye Module Federation-systemet fra Webpack 5, som skal bli utgitt med Angular 11 (https://www.angulararchitects.io/aktuelles/the-microfrontend-revolution-part-2-module-federation-with-angular/).
Svar #1
Jeg hadde det samme problemet, men jeg løste det ved å servere en json-fil til hovedappen med versjonene til underappene. Og cachte underappene ved hjelp av din hashede pakke.