因此,我的公司正在为我们的应用程序使用微前端架构。这是我在这里开创的一个项目,到目前为止,它相当成功。然而,我希望得到一些关于我们的一个突出挑战的建议。
当您使用Webpack构建JavaScript应用程序时,其中一个选项是向URL添加散列。此哈希是在每次构建时生成的,因此只有在文件本身发生更改时,哈希才会更改。因此,文件名应如下所示:
app.ab12cd.js
这样做的好处是浏览器缓存。浏览器将尝试缓存内容,以避免消耗太多数据。因此,如果它再次看到相同的文件名/URL,它将只使用缓存的版本,而不是重新下载它。由于文件名中的哈希值只有在文件经过更改后重新构建时才会更改,因此我们可以安全地依靠浏览器缓存此文件来减轻用户的在线下载负担,同时仍然相信他们将始终看到最新的更改。
这对我们的微前端架构来说是一个挑战。指导原则之一是每个微前端都是单独可发布的,这意味着在基础应用程序(即用户导航到的初始应用程序)和它将加载的微前端应用程序之间没有直接依赖关系。
我们通过简单的静态标记来实现这一点。每次我们添加一个新的微前端,我们只需要更新一次基础应用程序来添加一个新的标签:
<script src="micro-frontend/assets/js/app.js"></script>
在上面的示例中,使用nginx代理将该URL重定向到实际部署的微前端。对于涉及我们的企业基础设施的愚蠢和令人沮丧的原因,它是一个相对URL,但这是一个完全不同的切线。
要点是你会注意到它指向"app.js",而不是"app.12ab34.js“。我们不使用散列,因为我们不想每次微前端发生变化时都更新基础应用程序。相反,我们返回一个Cache-Control头,以防止浏览器缓存微前端。
这也是不理想的,因为虽然我们获得了独立性,但我们失去了对微前端代码的缓存。
所以,我的问题是:如果我们在微前端的文件名中启用哈希,是否有一种方法可以设置基础应用程序,使我们不必为哈希更改而对其进行更新?换句话说,有没有一种完全不同的方式来连接这些我还没有想到的应用程序呢?
非常感谢。
发布于 2019-10-28 08:32:40
您正在混合关注-缓存破坏和获取包的特定版本。
你可能不想为了小的更新而更新你的主要应用程序<script>
,但最终你需要以某种方式管理你的个人资产应该使用的版本。毕竟,这就是你为什么要做微前端的原因。
有很多选择可以做到这一点;其中一个选择是使用反向代理,它可以让你灵活地不改变主应用程序,无论何时发布新版本的包,它都会做一些事情,比如连接到工件存储库(例如npm注册表)的unpkg.com:
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>
的东西
当然,您仍然需要提出适当的客户端缓存(即发送正确的头部)。
另一种选择是,您可以在运行时进行组件的静态组合,而不是在主应用程序中进行静态组合:
<script>
标记以加载组件这将允许使用直接散列,并且您不必为客户端缓存崩溃而烦恼。
当然,这两种方法也可以混合使用--为你的主应用程序生成一个构建时的dep文件,让我们称它为package.json
,然后动态地加载它,并动态地生成<script>
标签,这些标签将从你的unpkg兼容的反向代理上加载你的组件。
unpkg.com
的软件是开源的,可以很容易地调整为与您自己的私有npm注册表相关联。
对于简单的PoC,您可以直接使用unpkg.com。
发布于 2020-08-21 18:02:12
如果您正在使用Webpack构建您的微前端,请使用WebpackManifestPlugin在输出目录中生成一个manifest.json。它将您的散列输出名称映射到json对象中的一个常量"main“属性。然后,当你想要从你的主应用加载微前端时,只需执行一次抓取(无缓存头和其他东西)来读取清单。然后使用scriptjs根据您从清单中获得的名称动态加载实际的包。
https://stackoverflow.com/questions/57693297
复制相似问题