微型前端-如何动态加载带有哈希值的URL

时间:2019-08-28 13:13:04

标签: javascript webpack hash micro-frontend

因此,我的公司正在为我们的应用程序使用微前端架构。这是我一直在这里开展的一个项目,到目前为止,它已经相当成功。但是,我希望就我们面临的一项重大挑战获得一些建议。

当您使用Webpack构建JavaScript应用程序时,一种选择是将哈希添加到URL。该哈希值是在每次构建时生成的,因此哈希值仅在文件本身发生更改时才会更改。所以文件名看起来像这样:

app.ab12cd.js

这样做的好处是浏览器缓存。浏览器将尝试缓存内容,以避免不得不消耗过多的数据。因此,如果再次看到相同的文件名/ URL,它将仅使用缓存的版本,而不是重新下载它。由于文件名中的哈希值只有在更改后重新生成文件时才会更改,因此我们可以安全地依靠浏览器将该文件缓存起来,以减轻用户的无线下载负担,同时仍然确信他们会始终查看最新更改。

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

我们通过简单的静态标签完成此操作。每次我们添加一个新的微前端时,我们只需更新一次基本应用程序即可添加一个新标签:

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

在上面的示例中,使用nginx代理将该URL重定向到实际的已部署微前端。由于涉及我们公司基础架构的愚蠢和令人沮丧的原因,它是一个相对URL,但这是另一个切线。

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

这也不是理想的,因为当我们获得独立性时,我们会释放微前端代码的缓存。

所以,我的问题是:如果我们要在微前端的文件名中启用散列,是否可以在无需更改哈希值的情况下就可以设置基本应用程序?换句话说,连接这些我还没有想到的应用程序是否有完全不同的方式?

非常感谢您。

2 个答案:

答案 0 :(得分: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.com的软件是开源的,可以轻松调整为与您自己的私有npm注册表关联。

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

答案 1 :(得分:-1)

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