Open ScriptedAlchemy opened 4 years ago
Hi,
I backport main features (exposes/remotes
) by migrate code by hand, works in https://github.com/alibaba/module-federation4/tree/master/examples. But shared
dose not work at present.
Compatibility layers between webpack4 and webpack5 sound a genius idea, which can keep good stuff in sync. I'd like to try this way.
I have invited you to be a collaborator :)
Excellent - shared is pretty complex to get perfect. Are you able to move shared modules into their own async dependency blocks? Where does it fail / how does it fail with shared, if i run the exmaples will i see the issue?
I can not find a way to move shared modules into async dependency blocks yet, so shared module which return a Promise
dose not works.
I try to implement this in branch feature/shared
, we can clone feature/shared
branch and follow https://github.com/alibaba/module-federation4#exmaple to see the issue.
Here’s a vanilla backport, with overrides working. It looks like the format the module is being returned as might be incorrect.
https://gist.github.com/ScriptedAlchemy/d386a094832dbd9a04324862d26570e9
Move dependency to async dependency block, make the source of the original request (import react from “react”) return a shared module with the module itself having a dependency that references the async block.
Then add a runtime requirement which is initialized when the app boots. You’d want to tap into either the require ensure or it’s object that is used to hydrate an array or object of key value chunks.
I’ll pull this down. But it looks close. Does the shared dependency ever load a js file? Is it a case of just not instantiating properly? Or is the execution that would / should trigger a require.ensure failing
Also, does the promise contain the code you’re after? Or is it like an empty object?
It looks, from the screenshot, like it’s attempting to access the object directly instead of a key that’s installed into the graph.
I’ll take a look tomorrow but it looks pretty close. If you get shared to split vendors out and perhaps try to load or reference the chunk. Then I think we can make this operable :) the import bootstrap code works to prevent early execution of the entrypoint. The idea being we can hoist additional shared code up and webpack can determine if it needs to load it’s own copy or if one has been supplied. When running as “host” it seems pointless to look for shared but it’s a limitation of the mechanism. We plan to internalize the import bootstrap code but it’s complex to do so in the webpack core
The promise contain the code of shared module already, it's from a async loaded js.
But the dependency is not a async dependency, also there is no bootstrap code for this logic now. So it get failed. I'll take some time to give a try.
Okay I think I understand what’s going on
Okay, so looking at the code - its not quite right. Overridables is tricky - you are missing a large portion of the plugin
Take a look at OverridablesPlugin
- you need more code in there from overridabels plugin. What you are trying to do right now is handle if or when Shared is an external, but shared is never an external. So it ends up looking for React but the code has been removed form the codebase entirely.
I see you are trying to split the chunks off. but i would remove this code
compilation.hooks.optimizeDependencies.tap(ModuleFederationPlugin.name, modules => {
compilation.dependencyTemplates.set(
ImportDependency,
new ImportDependency.Template()
);
for (let mod of modules) {
for (let i = 0; i < mod.dependencies.length; i ++) {
const dep = mod.dependencies[i];
if (dep && this.options.shared[dep.request]) {
// shared
mod.dependencies.splice(i, 1);
mod.blocks.push(new AsyncDependenciesBlock(
{},
dep.originModule,
dep.loc,
dep.request,
));
}
}
}
});
You need to have shared, be processed by https://github.com/webpack/webpack/blob/dev-1/lib/container/OverridablesPlugin.js https://github.com/webpack/webpack/blob/dev-1/lib/container/OverridableModule.js Pretty much all the overridable code is needed to make it work correctly with shared.,
/**
* @param {WebpackOptions} options webpack options
* @param {Compilation} compilation the compilation
* @param {ResolverWithOptions} resolver the resolver
* @param {InputFileSystem} fs the file system
* @param {function(WebpackError=): void} callback callback function
* @returns {void}
*/
build(options, compilation, resolver, fs, callback) {
this.buildMeta = {};
this.buildInfo = {};
const block = new AsyncDependenciesBlock({});
const dep = new OverridableOriginalDependency(this.originalModule);
block.addDependency(dep);
this.addBlock(block);
callback();
}
https://github.com/webpack/webpack/blob/dev-1/lib/container/OverridableOriginalDependency.js
this is how you should create SharedModulesm you have to go through dependency factories,
This might also help you understand how its built
mark
Any progress?
I am very busy this days, maybe I will take it again after a few weeks...
Here’s an example using v5 and v4 together. With some limits. https://youtu.be/tigwyK5Khck
A full backport is seemingly becoming a wider and wider gap. We recent rewrote most of the webpack graph and many other parts of the core. With the next beta feature tripling the capabilities it’s going to be very hard to maintain
wow, tripling 🤣
Here’s one example. There’s at least 6 others of this magnitude Advanced API: Module Federation for power users https://youtu.be/9F7GoDMrzeQ
Hello,
I’m one of the authors of Module Federation, responsible for the github issue mentioned in the readme.
Having built this mechanism - I might be able to provide insights on a backport. I currently have proprietary backports or compatibility layers running in production.
How’s the progression been on the backport?
I’ve had some success by pulling parts of the webpack 5 runtime into the compatibility layers. Creating a bi-directional interface between the two major webpack versions.