9

我为域根和第一个路径元素上的每个微前端使用“app-shell”类型的应用程序设置了几个微前端。每个应用程序都像一个独立的 Angular 应用程序一样构建,使用共享库来重用通用组件和功能。它们存在于自己独立的 docker 容器中,并使用 nginx 代理映射绑定在一起。

mydomain.com/         <- domain root app
            /child1   <- micro apps 
            /child2
            /child3
            /child4

我想设置一个角度服务工作者来缓存我们所有的资源。

第一次尝试

每个应用程序有一名服务人员。所以域根应用程序有一个,我们的每个“子应用程序”都有一个。那是; 每个ngsw-config.json独立的角度应用程序一个。

问题

这导致两个软件在每个子应用程序中争夺缓存控制权,用户最终可能会看到旧版本,具体取决于哪个获胜。

第二次尝试

让一个服务工作者来管理它们,将它放在域根应用程序上,并让它尝试使用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!');
    }
  }

问题

应该如何配置它以便服务工作者能够正确缓存我的资源,并且(如果每个应用程序需要一个)不会相互对抗?

编辑

对于其他在这个问题上苦苦挣扎的人;可能这可以使用 Webpack 5 中的新模块联合系统来解决,据说与 Angular 11 一起发布(https://www.angulararchitects.io/aktuelles/the-microfrontend-revolution-part-2-module-federation-with -角/)。

4

0 回答 0