Угловой 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 в основное приложение с версиями дополнительных приложений. И кэшировали дополнительные приложения с помощью вашего хешированного пакета.

Другие вопросы по тегам