Skip to content

Conversation

elbywan
Copy link
Contributor

@elbywan elbywan commented Aug 25, 2025

Summary

Use data.dependencies[0].request instead of create_data.raw_request to check if a module is declared in the MF shared configuration.

Without it and when using a custom resolver hooking into normalModuleFactory.hooks.resolve the fully qualified path would be used and would end up not matching anything.

This PR should restore the same behaviour as before v1.4.7 and specifically #10999

Related links

Checklist

  • Tests updated (or not required).
  • Documentation updated (or not required).

Copy link

netlify bot commented Aug 25, 2025

Deploy Preview for rspack canceled.

Built without sensitive environment variables

Name Link
🔨 Latest commit 6decd96
🔍 Latest deploy log https://app.netlify.com/projects/rspack/deploys/68af0db69fe0820008a344a0

Copy link

codspeed-hq bot commented Aug 25, 2025

CodSpeed Performance Report

Merging #11478 will not alter performance

Comparing elbywan:fix-mf-shared-custom-resolution (6decd96) with main (696026b)

🎉 Hooray! codspeed-rust just leveled up to 2.7.2!

A heads-up, this is a breaking change and it might affect your current performance baseline a bit. But here's the exciting part - it's packed with new, cool features and promises improved result stability 🥳!
Curious about what's new? Visit our releases page to delve into all the awesome details about this new version.

Summary

✅ 17 untouched benchmarks

@elbywan elbywan force-pushed the fix-mf-shared-custom-resolution branch from d316723 to a11b5d0 Compare August 26, 2025 08:01
@elbywan elbywan force-pushed the fix-mf-shared-custom-resolution branch from a11b5d0 to df5f9d9 Compare August 26, 2025 08:12
@elbywan elbywan marked this pull request as ready for review August 27, 2025 13:52
@Copilot Copilot AI review requested due to automatic review settings August 27, 2025 13:53
@elbywan elbywan requested a review from ahabhgk as a code owner August 27, 2025 13:53
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR fixes an issue with Module Federation's shared module matching by using the unresolved dependency request instead of the raw request from create data. This resolves problems where custom resolvers that hook into normalModuleFactory.hooks.resolve would cause fully qualified paths to be used, preventing proper matching against MF shared configuration.

  • Uses data.dependencies[0].request() instead of create_data.raw_request for shared module matching
  • Restores behavior that was changed in v1.4.7 via PR #10999
  • Fixes issue where custom resolvers would break shared module detection

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

return Ok(());
}
let request = &create_data.raw_request;
let dependency = data.dependencies[0]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a better way is use data.request here, should also solve the issue since dependency.request is assigned from data.request

Copy link
Contributor Author

@elbywan elbywan Aug 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👋 I tried to do that but it seems that data.request contains the mutated resolved path instead of the original request (since this change?). I could not find another practical way of retrieving it except extracting it from dependency[0].request which does contain the pristine specifier.

Copy link
Contributor

@ahabhgk ahabhgk Aug 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, have you tried webpack that they use the unresolved request or the changed request (changed by NormalModuleFactory.hooks.afterResolve)? If I remember correctly they will use the changed request. So at this point I'd like to keep the consistent with webpack

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh there is another issue about ConsumeSharedPlugin not using the changed request #11437 (your PR is about ProvideSharedPlugin not using original request)

Copy link
Contributor Author

@elbywan elbywan Aug 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I see this is more complicated than expected.

I see, have you tried webpack that they use the unresolved request or the changed request (changed by NormalModuleFactory.hooks.afterResolve)? If I remember correctly they will use the changed request. So at this point I'd like to keep the consistent with webpack

Oh, I can double check 👍.

What worries me is that if the logic is kept like this, it would make it very complicated to use a custom resolver - like with packages having subpath "exports" fields - because I'm not sure resolving all these paths ahead of time when generating the MF config + using the import field would be straightforward.

Especially with packages that only export deep subpaths, without root exports. ("exports": {"." { … } })

Oh there is another issue about ConsumeSharedPlugin not using the changed request #11437 (your PR is about ProvideSharedPlugin not using original request)

I'm wondering, what would be the expected outcome in this case? The consumer would load the module from the resolved path and assume that it is not provided by a producer?

In addition to this PR changes, I tried modifying the request to use the resolved path &data.request in the factorize hook here and it seems to solve both issues but I'm not fully sure that I get all the implications yet.

I'll try to dig into it and get a better understanding.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm curious how you use the custom resolver that resolves paths ahead of time. If you resolve paths before compile, you can use the resolved paths to generate a MF plugin (configured with resolved paths instead of the original paths) and apply to the compiler

Copy link
Contributor Author

@elbywan elbywan Aug 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that this is precisely the problem, I don't think that I can easily resolve all the possible subpaths for shared modules before compilation because I have no knowledge of the imports in the codebase. For simple cases it works, but as soon as I try to share a module exporting only subpaths it breaks (and the trailing slash syntax - module/ - does not work when using an absolute path fallback).

For instance, for these kind of packages…

{ "name": "package", "main": "index.js" }

…I cannot guess what the imports will look like in the provider code…

// any subpath is technically possible
import json from "package/package.json";
import stuff from "package/stuff";
import otherStuff from "package/other/stuff";
import someOtherStuff from "package/some/other/stuff";

…and it becomes very hard to generate the MF config:

new ModuleFederationPlugin({
  name: "host",
  shared: {
    package: {
      version: "1.0.0",
      import: // I can add the resolved path here but what about nested paths??
    },
    "package/": {
      version: "1.0.0",
      import: // won't work
    },
    // Does every possible import paths have to be added as keys here?
  },
}),

Whereas this config used to work just fine with v1.4.6:

new ModuleFederationPlugin({
  name: "host",
  shared: {
    package: {
      version: "1.0.0",
    },
    "package/": {
      version: "1.0.0",
    },
  },
}),

Copy link
Contributor

@ahabhgk ahabhgk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And need a test case to avoid regression

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
release: bug fix release: bug related release(mr only)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants