Угловой PWA в микрофронтендах
У меня есть несколько настроек микрофронтендов, использующих приложение типа "оболочка приложения" для корня домена и каждого микрофронтенда на первом элементе пути. Каждое приложение построено как отдельное приложение angular с использованием общих библиотек для повторного использования общих компонентов и функций. Они живут в собственном отдельном контейнере докеров и связаны вместе с помощью прокси-карт nginx.
mydomain.com/ <- domain root app
/child1 <- micro apps
/child2
/child3
/child4
Я хочу настроить сервис-воркер angular для кеширования всех наших ресурсов.
Первая попытка
У каждого приложения должен быть один сервисный работник. Таким образом, приложение с корневым доменом имело один, и каждое из наших "дочерних приложений" было одно. То есть; один
ngsw-config.json
на отдельное приложение angular.
Проблема
Это привело к борьбе двух SW за контроль кеша в каждом дочернем приложении, и пользователи могли в конечном итоге выбрать более старую версию в зависимости от того, какая из них выиграла.
Вторая попытка
Попросите одного сервис-воркера управлять ими всеми, поместите его в приложение корневого домена и пусть он пытается кэшировать ресурсы каждого "дочернего приложения", используя
ngsw-config.json
либо
assetGroup.resources.files
или же
assetGroup.resources.urls
. Казалось бы, ни один из них не отображает ресурсы дочерних приложений в свой кеш - по крайней мере, не при проверке репозитория DevTools AppCache, хотя вкладка сети действительно сообщает, что файл ресурсов обслуживается из ServiceWorker.
Проблема
Проблема здесь в том, что приложения больше не сообщают о развертывании новой версии. Я предполагаю, что это связано с тем, что angular-cli не имеет возможности узнать имя скомпилированных ресурсов во время сборки дочерних приложений. Они должны быть кэшированы во время выполнения. В любом случае, я не совсем уверен, что какие-либо из моих ресурсов вообще кэшируются. При переходе в офлайн-режим ничего не отвечает.
Кроме того, мы все еще иногда сталкиваемся с первой загрузкой более старой версии приложения корневого домена, и нам необходимо обновить страницу, чтобы получить обновленную версию. Я ввел код для очистки второго работника службы с моей первой попытки. Следующий код удаляет всех сервис-воркеров, зарегистрированных на
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());
});
}
Еще одно наблюдение, которое я вижу, заключается в том, что в хранилище DevTools / Application / Cache у меня есть ровно 4 записи на хэш новой версии, и он хранит все версии. Думал, что перезапишет кеш при обнаружении новой версии.
Текущая настройка:
Бег
@angular/service-worker
: 10.1.4
ngsw-config.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!');
}
}
Вопрос
Как это следует настроить, чтобы работники службы могли правильно кэшировать мои ресурсы и (если требуется по одному на приложение) не работать друг против друга?
РЕДАКТИРОВАТЬ
Для других, борющихся с этой проблемой; Возможно, это можно решить с помощью новой системы Module Federation из Webpack 5, которая, как говорят, будет выпущена вместе с Angular 11 (https://www.angulararchitects.io/aktuelles/the-microfrontend-revolution-part-2-module-federation-with-angular/).
1 ответ
У меня была такая же проблема, но я решил ее, передав файл JSON в основное приложение с версиями дополнительных приложений. И кэшировали дополнительные приложения с помощью вашего хешированного пакета.