Reputation: 1101
With Webpack 5 module federation if remote entry is modified, you don't need to redeploy main module/application and the newest version of the module will be loaded when it's requested by the browser.
I'm wondering: since the remote URL remains the same (e.g. http://localhost:8081/remoteEntry.js
), the browser probably will cache the file and cached version loaded every time you load the main module. On the other hand, if you add cache busting for remote entries, you will not have caching.
Let's assume that there is an application with micro-frontend architecture using Webpack 5 Module federation. There is a remote micro frontend with a config like:
output: {
publicPath: "http://localhost:8081/",
},
plugins: [
new ModuleFederationPlugin({
name: "app1",
filename: "remoteEntry.js",
exposes: {
"./Component1": "./src/Component1",
"./someModule1": "./src/someModule1",
},
})
]
and then main module config:
output: {
publicPath: "http://localhost:8080/",
},
plugins: [
new ModuleFederationPlugin({
name: "mainApp",
filename: "remoteEntry.js",
remotes: {
app1: "app1@http://localhost:8081/remoteEntry.js"
}
})
]
Both modules are deployed on production.
Then I change Component1
from app1
and deploy app1
module.
How to deal with remote modules caching?
UPDATE:
It looks like in my case the browser uses heuristic caching (https://www.rfc-editor.org/rfc/rfc7234#section-4.2.2) for remoteEntry.js
since the server doesn't provide explicit expiration times.
Thus, when remoteEntry.js
updates, the main application still loads this file from the cache that could be cached for weeks.
For chunks, it's not a problem since webpack could be configured to include hash in the file names.
For remoteEntry.js
I see 2 options:
Do you think it's a way to go?
Upvotes: 28
Views: 27581
Reputation: 71
You can use ExternalTemplateRemotesPlugin
for changing remoteEntry.js url template. I can fix this issue like code below;
new ModuleFederationPlugin({
name: 'my-app',
remotes: {
'my-remote-1': '[email protected]/remoteEntry.js?v=[Date.now()]',
...
},
...
}),
new ExternalTemplateRemotesPlugin(),
https://github.com/module-federation/module-federation-examples/issues/566 https://www.npmjs.com/package/external-remotes-plugin
Upvotes: 7
Reputation: 1278
In my opinion, you should never cache remoteEntry.js
since that's where the chunks mapping are. (Mapping here I mean between component and their chunk url). You always want to make sure you are displaying the latest remote chunk. If the mapping changed (usually just means the remote component updated), the browser should fetch the new chunk.
That said, you should cache busting the chunks using
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"
})
],
in your webpack.config.js
recommended here https://webpack.js.org/guides/caching/
This way, again, the host will always try to fetch the remoteEntry.js
(a fixed url that do not have hash) and let the browser fetch the new chunk url if the hash are changed.
Upvotes: 0
Reputation: 2601
Cache busting implies to re-build (or, at least, post-process) the main app bundle, and that is one of the problem module federation tries to avoid.
So, considering remoteEntry.js
is usually a small file, the best solution is to apply a specific cache control for this file so it never gets cached.
With nginx, it can be done that way:
location ~ .*remoteEntry.js$ {
expires -1;
add_header 'Cache-Control' 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
}
Upvotes: 22
Reputation: 185
I maybe a bit late to the party but here is one of the solution where you append a random string at the end of your remoteEntry at build time . https://github.com/module-federation/module-federation-examples/issues/566#issue-785273439
Upvotes: -1
Reputation: 179
I don't think this is a concern since webpack adds cache busting to your application's js files during the build process. Take a look at the HTML code that is returned when you load your app and you will notice that the tags that load your bundle are different after each deployment. remoteEntry.js
is the module federation way of allowing your app to be loaded from a remote server, not your actual app code.
Upvotes: -4