Building a Web Package Manager for Micro‑Frontend Module Federation on Webpack 4
This article explains how the WPM (Web Package Manager) was created to enable micro‑frontend resource sharing and hot‑module updates on legacy Webpack 4 projects, detailing the challenges of missing module‑federation support and the custom plugins and loaders that bridge the gap.
Micro Frontend Package Management Platform – WPM (Web Package Manager)
To further share resources and improve efficiency, the Weimob technical team abstracted WPM, which can be thought of as a web‑based npm. A WPM package does not need to be installed or participate in the application build process; each package has its own version and environment, and is built and published independently.
WPM packages can be JSON files, components, or functions, achieving resource‑level sharing while addressing several industry challenges.
Company has many Webpack 4 projects that cannot use module‑federation
Without module‑federation , all remote modules must be loaded with systemjs . This only affects the timing of ref acquisition for component modules, but when the remote module is a configuration (JSON) or a function, every subsequent synchronous logic must be forced into a Promise, which is inconvenient and error‑prone.
We implemented import‑http‑webpack‑plugin (which uses systemjs to synchronously import HTTP resources) to match the main capabilities of MF, along with wpm‑webpack‑plugin (hot‑update/upload and package version publishing), wpmjs SDK (semantic version import via systemjs), wpm‑dev‑panel (auto‑connect local dev environment), wpm‑cli (CLI tool), and wpm‑http‑api (permission/version management) to provide a complete WPM solution.
Micro‑frontend development mode component hot‑update
Because frameworks like Vue and React require their development builds for hot‑update, and React has stricter conditions, WPM’s React and Vue packages are not built through the host project but are independently bundled. Therefore WPM provides a development mode and maintains vue‑dev and react‑dev packages to enable hot‑update for any independently started module.
React hot‑update requirements: react‑refresh, react‑dom, react singleton react‑dom and react must use the development version Ensure execution order; react‑refresh must run before react‑dom Use @pmmmwh/react-refresh-webpack-plugin
@module‑federation/webpack‑4
Although import‑http‑webpack‑plugin can generate fewer chunks than module‑federation , chunk count is irrelevant with HTTP/2.0. Module‑federation already provides strong base capabilities for SSR, TypeScript, etc., and third‑party Vite plugins exist. We therefore adopted the MF ecosystem and implemented @module‑federation/webpack‑4 to support WPM upgrades; the package is now an official MF capability.
Implementation principle of module‑federation/webpack‑4
How do Webpack 4 and Webpack 5 interoperate? Three key points:
usemf – use the SDK built by Webpack 5 to simulate a Webpack 5 environment in non‑Webpack 5 contexts for loading module‑federation.
Follow the module‑federation loading flow (init all remote containers, merge shareScopes, restore Webpack 5 share rules) and output a module‑federation‑container.
// container
{ async init(shareScope){}, get(name){ return async factory() } }
// shareScopes example
{ default: { react: { "18.0.2": { get(){ return async function factory(){ return module } }, ...other }, "17.0.2": { get(){ return async function factory(){ return module } }, ...other } } }Enable jsonp‑chunk in Webpack 4 to wait for remote module loading.
The above process is realized through plugins (illustrated in the diagram).
Add a new entry to implement the module‑federation loading flow and output the container.
Intercept remote module loading; instead of loading local modules directly, use remote modules.
Intercept shared module loading; replace local loading with remote loading.
All shared requests are intercepted, but a shared bundle is still emitted, and the loading function merges shareScopes.
The two red areas in the diagram show how the Webpack 4 loading flow is altered to support remote module loading.
Intercept import and leave a dependency marker.
Set an alias that points to a non‑existent URL (only non‑existent paths can be intercepted).
In compiler.resolverFactory.plugin('resolver normal'), use the resolver.hooks.resolve.tapAsync hook to forward the request to import‑wpm‑loader.js.
The loader inserts a tag that marks the remote package for chunk waiting.
Make jsonp‑chunk wait for remote dependencies.
Match remote module dependencies with a regular expression and delay chunk execution.
Patch the jsonp loading function to support waiting for remote loads.
Source code snippets
// module-federation/webpack-4/lib/plugin.js
apply(compiler) {
// 1. Generate a unique jsonpFunction global variable to avoid conflicts
compiler.options.output.jsonpFunction = `mfrename_webpackJsonp__${this.options.name}`
// 2. Generate four virtual modules for later use
this.genVirtualModule(compiler)
// 3. Initialize remote module mapping in entry chunks
this.watchEntryRecord(compiler)
// 4. Load all containers in entry chunks to initialize shareScopes
this.addLoader(compiler)
// 5. Generate the MF entry file (usually remoteEntry.js)
this.addEntry(compiler)
this.genRemoteEntry(compiler)
// 6. Intercept compilation of remotes and shared modules
this.convertRemotes(compiler)
this.interceptImport(compiler)
// 7. Make webpack jsonp chunk wait for remote dependencies
this.patchJsonpChunk(compiler)
this.systemParse(compiler)
} // import-wpm-loader.js
module.exports = function() {
`
/* eslint-disable */
if (window.__wpm__importWpmLoader__garbage) {
// 1. Leave a tag to mark the remote package for chunk waiting
window.__wpm__importWpmLoader__garbage = "__wpm__importWpmLoader__wpmPackagesTag${pkgName}__wpm__importWpmLoader__wpmPackagesTag";
}
// 2. When this module runs, the remote module has been loaded; get its sync value
module.exports = window["__mfplugin__${mfName}"].get("${decodeURIComponent(pkgName)}")
`
}Appendix
Concept introduction to module‑federation: https://module-federation.github.io/blog/get-started
@module‑federation/webpack‑4 (open source): https://github.com/module-federation/webpack-4
WPM introduction (not open source): https://wpm.hsmob.com/assets/wpm-docs/Standard.html
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
