WP5 模块联合:remoteEntry.js 缓存

Posted

技术标签:

【中文标题】WP5 模块联合:remoteEntry.js 缓存【英文标题】:WP5 Module Federation: remoteEntry.js caching 【发布时间】:2021-04-06 07:07:05 【问题描述】:

如果修改了远程入口,使用 Webpack 5 模块联合,您无需重新部署主模块/应用程序,并且会在浏览器请求时加载最新版本的模块。

我想知道:由于远程 URL 保持不变(例如http://localhost:8081/remoteEntry.js),浏览器可能会在您每次加载主模块时缓存加载的文件和缓存版本。另一方面,如果您为远程条目添加缓存清除,您将没有缓存。

假设有一个使用 Webpack 5 模块联合的微前端架构的应用程序。有一个远程微前端,其配置如下:

output: 
  publicPath: "http://localhost:8081/",
,
plugins: [
  new ModuleFederationPlugin(
    name: "app1",
    filename: "remoteEntry.js",
    exposes: 
      "./Component1": "./src/Component1",
      "./someModule1": "./src/someModule1",
    ,
  )
]

然后是主模块配置:

output: 
  publicPath: "http://localhost:8080/",
,
plugins: [
  new ModuleFederationPlugin(
    name: "mainApp",
    filename: "remoteEntry.js",
    remotes: 
      app1: "app1@http://localhost:8081/remoteEntry.js"
    
  )
]

这两个模块都部署在生产环境中。

然后我将 Component1app1 更改并部署 app1 模块。

如何处理远程模块缓存?

更新:

在我的情况下,浏览器似乎对remoteEntry.js 使用启发式缓存 (https://www.rfc-editor.org/rfc/rfc7234#section-4.2.2),因为服务器没有提供明确的过期时间。

因此,当remoteEntry.js 更新时,主应用程序仍会从可能缓存数周的缓存中加载此文件。 对于块,这不是问题,因为 webpack 可以配置为在文件名中包含哈希。

对于remoteEntry.js,我看到了 2 个选项:

缓存清除 明确指定缓存控制

你认为这是一条路吗?

【问题讨论】:

【参考方案1】:

在我看来,你永远不应该缓存remoteEntry.js,因为那是块映射所在的位置。 (这里的映射是指组件和它们的块 url 之间的映射)。你总是想确保你显示的是最新的远程块。如果映射改变(通常只是意味着远程组件更新),浏览器应该获取新的块。

也就是说,您应该使用缓存破坏块

    output: 
        filename: '[name].[contenthash].js',
    ,
    plugins: [
        new container.ModuleFederationPlugin(
            name: "RemoteModule",
            library:  type: "var", name: "RemoteModule" ,
            filename: "remoteEntry.js",
            exposes: 
                './SuperButton': "./src/components/SuperButton",
                './SuperButton2': "./src/components/SuperButton2",
            ,
            shared: 
                react:  singleton: true, eager: true ,
                "react-dom":  singleton: true, eager: true ,
            
        ),
        new htmlWebpackPlugin(
            template: "./public/index.html"
        )
    ],

在你的webpack.config.js这里推荐https://webpack.js.org/guides/caching/

这样,主机将再次尝试获取remoteEntry.js(没有哈希的固定网址),如果哈希更改,则让浏览器获取新的块网址。

【讨论】:

我完全同意你的观点,你不应该缓存remoteEntry.js,它应该总是一个“新鲜”的版本。也就是说,我认为您提出的解决方案不会影响remoteEntry.js 的缓存。 [name].[contenthash].js 对于单个项目来说是非常好的解决方案,因为 webpack 解析了 [name].[contenthash].js 的版本并插入到 index.html 中,此外,它还创建了相关的 .js 文件。对于remoteEntry.js,情况并非如此,因为端点是在单独的应用程序中指定的,并且在微前端应用程序重建后无法获得“更新”的名称。 恕我直言,[name].[contenthash].js 仍然可以在多个项目中使用。 "With remoteEntry.js it's not the case since the endpoint is specified in separate application and there is no way to get the 'updated' name after micro-frontent application rebuilds." 有了这个评论——其他主机不必知道块 url 对吗?为了使用暴露的远程组件,您只需要知道remoteEntry.js url 和暴露的公共名称。 我可能误会了你。但是为了澄清,remoteEntry.js url 不应该在构建之间改变(因此在 url 中不能有哈希)。唯一更改它的时间可能是因为远程组件发生了重大更改或其他需要 remoteEntry.js 具有 version bump 的原因。其余的远程块 url 应该被散列。让我更新我在上面添加的代码 sn-p 以在 ModuleFederationPlugin 中包含 filename 属性以使其清楚。如果我们添加filename 属性,remoteEntry.js 名称将没有哈希。 这将是一个固定的网址。让我知道这是否有意义! @PavloKozlov 我认为我们在谈论同样的事情 ;) 实际上,您可以在块名称中使用 contentHash,并且 remoteEntry.js(端点本身)与缓存策略 -> 无缓存保持相同。请参阅上面@ebrehault 的答案【参考方案2】:

缓存破坏意味着重新构建(或至少后处理)主应用程序包,这是模块联合试图避免的问题之一。

因此,考虑到remoteEntry.js 通常是一个小文件,最好的解决方案是对该文件应用特定的缓存控制,使其永远不会被缓存。

使用nginx,可以这样做:

location ~ .*remoteEntry.js$ 
    expires -1;
    add_header 'Cache-Control' 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';

【讨论】:

【参考方案3】:

我参加聚会可能有点晚了,但这是一种解决方案,您可以在构建时在 remoteEntry 末尾附加一个随机字符串。 https://github.com/module-federation/module-federation-examples/issues/566#issue-785273439

【讨论】:

是的,但为此我们必须重建主机:(【参考方案4】:

我不认为这是一个问题,因为 webpack 在构建过程中将缓存清除添加到应用程序的 js 文件中。查看加载应用程序时返回的 HTML 代码,您会注意到加载包的标签在每次部署后都不同。 remoteEntry.js 是模块联合方式,允许从远程服务器加载您的应用程序,而不是您的实际应用程序代码。

【讨论】:

你是对的,因为 webpack 在构建文件时会为文件名添加哈希值。 remoteEntry.js 有点不同。文件名中没有缓存破坏者或哈希。只是remoteEntry.js。我在一个简单的应用程序上对其进行了测试,remoteEntry.js 有时会使用200 解析,有时会使用304 http 状态码。我不确定背后的原因是什么。 这对您的应用程序有何影响?你看到缓存版本了吗?如果是这样,它可能是别的东西。可能是您的托管服务提供商缓存您的 HTML 页面的问题,而不是 remoteEntry.js 对我来说,它工作正常。我创建了另一个示例并将其部署在 heroku 上。 remoteEntry.js 在我第一次加载或远程版本已更改时使用 200 代码解析。否则,它将使用304 http 状态代码解析。我只是想在迁移现有应用程序并将其部署到生产环境之前确定缓存是如何工作的。 我还用最新发现和可能的解决方案更新了帖子。

以上是关于WP5 模块联合:remoteEntry.js 缓存的主要内容,如果未能解决你的问题,请参考以下文章

WP5 Module Federation:单例实例化多次

Django 集成Redis缓存库

易语言EXUI登录界面(附带缓动效果)源码

7-网络芯片CH395Q学习开发-模块使用Socket0-5作为6路TCP客户端和电脑上位机TCP客户端局域网通信(Socket缓存区配置)

Webpack 5 模块联合:使用身份验证访问远程模块

Webpack 模块联合不适用于急切的共享库