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?
remoteEntry. js is the module federation way of allowing your app to be loaded from a remote server, not your actual app code.
Module Federation allows loading separately compiled applications at runtime. Also, we can share common dependencies. This also allows sharing common data like information on the current user or global filters.
Introduced in Webpack 5, the Module Federation plugin gives developers a way to create multiple separate builds that form a single application. Any JavaScript application that is bundled with Webpack 5.0 or greater can dynamically load or share code and dependencies with any other at runtime.
The ModuleFederationPlugin allows a build to provide or consume modules with other independent builds at runtime. const { ModuleFederationPlugin } = require('webpack'). container; module.
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.
Because webpack-assets-manifest doesn't generate an entry for remoteEntry.js (a file used by Module Federation to bootstrap remotes), we will fetch it by name only. Note: remoteEntry.js is considered a local chunk in the remote repository. Next, we're getting all remote chunks and returning the code.
In addition, module federation does not need to load the main entry point or another entire application. It only needs to load the needed code, i.e. a few kilobytes of code. This approach works with any JavaScript code without redundant packages for shared utilities and components.
ModuleFederationPlugin combines ContainerPlugin and ContainerReferencePlugin. It should be possible to expose and use any module type that webpack supports. Chunk loading should load everything needed in parallel (web: single round-trip to server). Overriding modules is a one-directional operation.
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';
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With