3

所以我的公司正在为我们的应用程序使用微前端架构。这是我一直在这里开创的一个项目,到目前为止它非常成功。但是,我希望就我们面临的一项突出挑战获得一些建议。

当您使用 Webpack 构建 JavaScript 应用程序时,其中一个选项是向 URL 添加哈希。每次构建都会生成此哈希,因此只有在文件本身发生更改时哈希才会更改。所以文件名看起来像这样:

app.ab12cd.js

这样做的好处是浏览器缓存。浏览器会尝试缓存一些东西以避免消耗过多的数据。因此,如果它再次看到相同的文件名/U​​RL,它将只使用缓存的版本,而不是重新下载它。因为文件名中的哈希只有在文件被重新构建时才会改变,所以我们可以安全地依赖浏览器缓存这个文件来减少我们用户的在线下载负担,同时仍然相信他们将永远查看最新更改。

这是我们的微前端架构面临的挑战。指导原则之一是每个微前端都可以单独发布,这意味着基础应用程序(即用户导航到的初始应用程序)和它将加载的微前端应用程序之间没有直接依赖关系。

我们通过简单的静态标签来实现这一点。每次我们添加一个新的微前端,我们只需要更新一次基础应用来添加一个新的标签:

<script src="micro-frontend/assets/js/app.js"></script>

在上面的示例中,该 URL 使用 nginx 代理重定向到实际部署的微前端。由于涉及我们公司基础设施的愚蠢和令人沮丧的原因,这是一个相对 URL,但这是完全不同的。

重点是您会注意到它指向“app.js”,而不是“app.12ab34.js”。我们没有使用哈希,因为我们不想在每次微前端更改时更新基础应用程序。相反,我们返回一个 Cache-Control 标头以防止微前端的任何浏览器缓存。

这也不理想,因为在我们获得独立性的同时,我们失去了对微前端代码的缓存。

所以,我的问题是:如果我们要在微前端的文件名中启用哈希,有没有一种方法可以设置基础应用程序,我们不必为哈希更改更新它?换句话说,有没有一种完全不同的方式来连接这些我还没有想到的应用程序?

太感谢了。

4

2 回答 2

0

您正在混合关注点 - 缓存破坏和获取特定版本的包。

您可能不想<script>只为小的更新而更新您的主要应用程序,但最终您需要以某种方式管理应该使用哪个版本的个人资产。毕竟这就是为什么你可能在做微前端的原因。

有很多选择可以做到这一点;一个选项可以让您灵活地不更改主应用程序,每当发布新版本的包时,使用反向代理,即执行类似于 unpkg.com 连接到您的工件存储库(例如 npm 注册表)的操作):

  • -> unpkg.com/:package@:version/:file如果您采用这种模式,您不仅可以更新您的版本,还可以获得语义版本控制的好处。您可以在不影响主要应用程序的情况下发布主要更新和次要更新

  • 因此<script src="micro-frontend/assets/js/app.js"></script>会变成类似<script src="my-own-nginx/@micro-frontend/assets-a@1.2.*/"></script>

当然,您仍然需要提出适当的客户端缓存(即发送正确的标头)。

另一种选择是,您可以在运行时进行,而不是在主应用程序中进行组件的静态组合:

  • 从服务中获取最新的组件列表(为简单起见, package.json 也足够了)
  • 动态创建<script>标签以加载组件

这将允许使用直接哈希,并且您不必为客户端缓存破坏而烦恼。

当然,这两种方法也可以混合使用——为你的主应用程序生成一个构建时间 dep 文件,让我们调用它package.json并动态加载它并动态生成<script>标签,这些标签会将你的组件从与 unpkg 兼容的反向代理中加载出来。

该软件unpkg.com是开源的,可以轻松调整以与您自己的私有 npm 注册表相关联。

对于简单的 PoC,您可以直接使用 unpkg.com。

于 2019-10-28T00:32:40.047 回答
-1

如果您使用 Webpack 构建微前端,请使用 WebpackManifestPlugin 在输出目录中生成 manifest.json。它将您的哈希输出名称映射到 json 对象中的常量“主”属性。然后,当您想从主应用程序加载微前端时,只需执行 fetch(无缓存标头和内容)即可读取清单。然后使用 scriptjs 以您从清单中获得的名称动态加载实际的包。

于 2020-08-21T10:02:11.663 回答