-
-
Notifications
You must be signed in to change notification settings - Fork 8.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: Consumption of eager shared modules #18062
base: main
Are you sure you want to change the base?
Conversation
|
For maintainers only:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/cc @ScriptedAlchemy what do you think about these changes
Any updates? |
Don't worry, I will ping you when we need some advices/dicussions, I am fine with your changes |
@2hea1 Do we need to port this back to module-federation/enhanced or did our rewrite already address all these problems? |
@ScriptedAlchemy @cmath10 I use related pr: cmath10/module-federation-incorrect-version-resolution#1 |
@2heal1 Is this part required: In my app when I build it for production, all files and pages are served by the same NGINX server and I have URLs like |
@ScriptedAlchemy Are you fine with these changes? |
@cmath10 ahh i got you , the port can be removed cmath10/module-federation-incorrect-version-resolution@03377bc |
@2heal1 Thanks for the reply! I'll check the solution as soon as possible. |
@2heal1 That works, but now I have a question. As I understand, mf-manifest is loaded via a network to get info about a federated module. I noticed there is no hash in the manifest's name and wonder how that will work if a browser caches it. Or do I understand it incorrectly? |
@cmath10 I'm a little out of context, we still need this fix, am I right? |
@alexander-akait yes, if there is no solution for caching. |
Yes, this is a question . But since you can control server to dispatch data , so you can use our First you can generate snapshot by invoking Second, set mf runtime plugin to consume the And when the remote need to be loaded , it will just use the remoteEntry , and the real entry has hash ,so it will not have the cache issue . That's also what we have done in bytedance . I hope it can help you as well. |
@cmath10 Feel free to ping when you try the solutions and decide there is no solution |
I need to port it to PHP first 😅 |
@2heal1 this is the only solution? |
Yes.. But i feel like this is not very different from the original demo. |
@alexander-akait i think this discussion got a little off topic on the pull request, overall i think this is a problem that should be resolved in webpack as this is a problematic issue. If a module is eager, it should use the best eager version available. typically this would have to be the host as app could already be using it and host may not consume remote before entry is already consuming. This seems like a valid issue and the PR seems to solve some conditions @cmath10 From what i understand. You have two aspects
I believe the main cause of the issue here is related to a synchronous startup in your host, along with a runtime chunk of single set. Without can import(bootstrap), any async setup causes a failure to the sync side of the application. For this use case, there is one alternative - however if this solution solves eager consumption - Id be interested in seeing if it solves mine. I chose to integrate an internal async boundary within the runtime code of entrypoints. So that users of single runtime chunk or cannot use import() in entry, do not have to change application architecture to achieve the same effect. https://github.com/module-federation/universe/blob/main/packages/enhanced/src/lib/container/AsyncBoundaryPlugin.ts - which makes entire application startup async at the runtime level. Everything starts like an import() would. This means you could depend on async chunks that "eagerly" required, since theres no eager aspect anymore. Can you ellaborate a little further on you pull request and how the logic here is applied? Is your strategy to search share scope for a already resolved and avaliable version in share scope? or are you able to await a promise and not crash the host with this alteration in consume shared module loading? @alexander-akait i believe that while this solves a specific scope of issue, i do think there is a series of bugs in webpack where single runtime chunk and multiple entry points cause several points of failure. Single runtime chunk causes container reference modules to only be hoisted to their relative entry points. Routing between multiple entry (like nextjs) will cause container init to fail as webpack runtime is unable to init all the modules for containers referenced in its initExternal() callbacks. The inability for sync startup is quite painful, eager consumption also will apply to remote module imports too if unwrapped in async boundary somewhere in loading chain, causing call of undefined. Most use cases the user is already loading entrypoint via some promise implementation. if entry startup is async and entrypoiint called its own webpack_require.f() chunk handlers for the entry point, before entry startup runtime module calls its webpack_require(entry.module), this would resolve most eager consumption issues. |
Currently, I use in my project a version of webpack, modified exactly in the same manner I propose here. And it works, despite of tons of legacy I have to deal with. I'll try your alternative to check if it works. Need a few days to finish some tasks before. |
Thats acceptable. This sounds like a legit issue and im pretty use other users have been bitten by this. @alexander-akait we should merge if all requirements are met. |
/cc @vankop Can take a look at it too? |
I guess we need to add a test case. There is a folder with container test cases |
@cmath10 Yeah, can you add a couple test cases and we can merge |
From the original discussion:
and from further discussion: #18001 (reply in thread) Well, I don't refuse, and experience of writing tests for webpack would be a great thing, but I need a little help at least first 😅 |
@cmath10 Sorry for delay, you can find examples here - https://github.com/webpack/webpack/tree/main/test/configCases/container, as you can see write them is not hard, so just put coumple examples with eager shared modules (which we fixed here), if you need more help feel free to write me |
7a79511
to
ffaad71
Compare
@cmath10 Thanks for your update. I labeled the Pull Request so reviewers will review it again. @alexander-akait Please review the new changes. |
@alexander-akait, I just rebased my branch, so I think a new review is not required yet. However, I have some questions:
I intend to use the following:
{
"dependencies": {
"tiny-emitter": "=2.0.0"
}
}
import TinyEmitter from 'tiny-emitter'
const emitter = new TinyEmitter()
emitter.on('hello', () => console.log('hello[host]'))
emitter.emit('hello')
import('service/emitter').then(({ emitter }) => {
emitter.emit('hello')
})
{
"dependencies": {
"tiny-emitter": "^2.1.0"
}
}
const { dependencies } = require("./package.json");
// eslint-disable-next-line n/no-unpublished-require
const { ModuleFederationPlugin } = require("../../../../").container;
/** @type {import("../../../../").Configuration} */
module.exports = {
plugins: [
new ModuleFederationPlugin({
name: "remote",
filename: "[name].[fullhash].js",
library: { type: "var", name: "service" },
exposes: {
"./emitter": {
name: "emitter",
import: "./emitter.js"
}
},
shared: {
...dependencies
}
})
]
}; In my test case, I'm going to use |
What kind of change does this PR introduce?
Fixes eager consumption of shared dependencies. Full description is in this discussion: #18001 (reply in thread)
Did you add tests for your changes?
No, the reason for no tests attached can be found in the discussion link above. cc @alexander-akait
Does this PR introduce a breaking change?
No, as far as I understand how webpack container works.
What needs to be documented once your changes are merged?
This is yet to be defined, this PR is needed as a starting point.