Home > Software design >  Prevent ID collisions in independent Federated modules
Prevent ID collisions in independent Federated modules

Time:02-16

I am trying to import two modules using Webpack's federated module plugin with a setup like this:

new ModuleFederationPlugin({
    name: "module-a",
    filename: "remoteEntry.js",
    library: { type: "var", name: "module_a" },
    exposes: {
        "./lib": "./bootstrap",
    },
})

and a nearly identical setup for module-b.

However, since both of the federated modules use the same file name at their root module (e.g. bootstrap.ts), both get assigned the same chunkId ("626", which is just the hash of './node_modules/ts-loader/index.js!./bootstrap.ts' using the numberHash function)

In a normal webpack build, the file paths for each chunk would be unique, but since I have multiple federated modules that expose a ./bootstrap.ts, each get the same chunk id (656, in this case). This causes an id collision in the runtime, as both federated modules request the same chunkid, and as result there is a race condition, wherein the first chunk with the id 626 to be requested gets used by both federated modules.

I tried setting outputs.chunkFilename: "module-a-[id].js" (and likewise for module-b) but this doesn't seem to change the chunkId, and in the network activity, I can see that only one of the two chunks gets loaded and is imported (erroneously) into both federated modules. For example, in the network tab, I can see that either module-a-656.js or module-b-656.js gets loaded -- but never both, and the contents of whichever file gets loaded end up being imported into both modules.

Reading the code, it looks like the chunk IDs get set by the DeterministicChunkIdsPlugin, which doesn't expose a hashSalt option or make use of the options.hashSalt (i.e. in order to salt the ids with the name of the federated module), so there doesn't seem to be a way change the hashing function to prevent id collisions.

Is there any way to prevent this kind of id collisions with federated modules? (other than to manually check that none of the federated modules that your app might want to import ever expose the same file names)

CodePudding user response:

The race condition I was asking about came about because of an (as of this writing) undocumented feature which is that the Federated Module Plugin uses the name field from the package.json file to resolve assets from federated modules. Otherwise assets with common paths (e.g. src/index.js) from separate federated modules become ambiguous from webpack's perspective, and create a race condition which depends on the order in which network requests are completed.

In my testing of this plugin, I copied one module into another folder, made a small change to the copy, and tried to import both copies as federated modules -- only to find that the contents of whichever module's remoteEntry.js network request finished first was injected into both modules on the page.

Here's a repo illustrating this particular "gotcha" of working with federated modules.

  • Related