Open harrisKAsher opened 1 week ago
Hi, you can use this plugin to update your remotes in the host application when something is changing
Hi, I am not sure how that helps? I thought this package was suppose to work with HMR by default? I didn't see anything in the Documentation that I needed to use a separate plugin to get HMR.
That being said, I am not sure what your are suggesting what I do with that plugin, would it be putting something like this in my host/vite.cofnig.ts?
ViteRestart({
restart: [`${env.parsed?.VITE_CORE_URL}/assets/remoteEntry.js`]
})
If so, that doesn't work.
Yep, you need to add this plugin in the host vite configuration. It takes the file system paths to watch
Okay... That is a touch disappointing as I was hoping there would be a way to have the reset just happens. The way your describing would require me to have every developer edit the path so that it points to their location on their machine.
I guess to elaborate a bit more, my hope was to have my host app allow connections from other teams and be hosted on an AWS S3 Bucket. Then we could point the Host at the remote localhost and we could develop that way so other teams didn't have to have access to the host app. But I am assuming that is not possible, correct? (Just a note, I did test that concept with @originjs/vite-plugin-federation, it works, just couldn't do HMR.)
Im not sure if vite ever natively supported hmr, as far as i know fast refresh and hmr only work in webpack and rspack based builds as a built-in solution.
The built-in HMR in Vite works well. You can see it in action by starting both the host and remote in dev mode.
Your host is in build mode, and the remote is in dev mode. For this scenario, additional configuration is required.
1. React must use the development version.
2. react-refresh should be a singleton.
3. Install React Chrome DevTools.
Does my chrome dev tools for federation work with this package? Id so we have a module proxy that comes with fast refresh and hmr baked in. Allows us to hmr and develop against production with a local override
Does my chrome dev tools for federation work with this package?
yes
Can it bypass the rules of React Refresh?
When you enable hmr switch a runtime plugin is added that uses resolve share hook and injects react runtime and dev versions from unpkg
When you enable hmr switch a runtime plugin is added that uses resolve share hook and injects react runtime and dev versions from unpkg
Then it should theoretically be supported already. I’ll check the shared configuration soon and see how to adapt it to work with @vitejs/plugin-react.
@harrisKAsher Have you tried the Module Federation Chrome extension?
@ScriptedAlchemy Didn’t see unpkg.
Does a prod and dev mix work tho? Give it a try. What i know is the devtool implements a dev react to bypass mixing issues. Check if the chrome tools runtime plugin is added in the federation globals. It might be something we just import and add in our plugin. Not sure if extention injects it or if we auto register it on our side
@zhangHongEn I just installed the Module Federation Chrome extension to try it out and no matter what I do I get told "No ModuleInfo Detected".
@zhangHongEn I just installed the Module Federation Chrome extension to try it out and no matter what I do I get told "No ModuleInfo Detected".
Did you use the json remote protocol. Not the js one
No, I am using the js
one. I tried just renaming the entry to be remoteEntry.json
but that just results in a JSON parse error. I have also added manifest: true
to each of my configs as the error message suggested that could be the problem. But it seems to be my files are still being generated as a js file not a json file. (I will include the error below in case it helps).
Error: [ Federation Runtime ]: [ Federation Runtime ]: [ Federation Runtime ]: Failed to get manifest.
args: {"manifestUrl":"http://localhost:3110/assets/remoteEntry.json","moduleName":"globalStore"}
https://module-federation.io/guide/troubleshooting/runtime/RUNTIME-003
Original Error Message:
SyntaxError: JSON.parse: unexpected character at line 2 column 3 of the JSON data
The docs state you have to use the json protocol. A js file should emit alongside something like mf-manifest.json
@harrisKAsher mf-manifest.json https://module-federation.io/configure/manifest.html
Okay, I think I am making progress.
Here is what my host one looks like now, the core and globalStore one looks really similar.
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { federation } from '@module-federation/vite';
import dotenv from 'dotenv';
const env = dotenv.config({ path: `../../.env` });
export default defineConfig({
plugins: [
federation({
name: 'host',
manifest: {
fileName: 'mf-manifest.json'
},
remotes: {
core: `core@${env.parsed?.VITE_CORE_URL}/mf-manifest.json`,
globalStore: `globalStore@${env.parsed?.VITE_GLOBAL_STORE_URL}/mf-manifest.json`
},
shared: {
react: {
singleton: true
},
'react-dom': {
singleton: true
},
'react-router-dom': {
singleton: true
}
}
}),
react()
],
build: {
modulePreload: false,
target: 'esnext',
minify: false,
cssCodeSplit: false
}
});
But when I try to run this it gets stuck in an infinite loop stating
[ Federation Runtime ]: The remote "core" is already registered. If you want to merge the remote, you can set "force: true".
Says the same thing about globalStore as well.
And in case it helps, this is what mf-manifest.json looks like on host.
{
"id": "host",
"name": "host",
"metaData": {
"name": "host",
"type": "app",
"buildInfo": {
"buildVersion": "1.0.0",
"buildName": "host"
},
"remoteEntry": {
"name": "remoteEntry-[hash]",
"path": "",
"type": "module"
},
"ssrRemoteEntry": {
"name": "remoteEntry-[hash]",
"path": "",
"type": "module"
},
"types": {
"path": "",
"name": ""
},
"globalName": "host",
"pluginVersion": "0.2.5",
"publicPath": "/"
},
"shared": [
{
"id": "host:react",
"name": "react",
"version": "18.3.1",
"requiredVersion": "^18.3.1",
"assets": {
"js": {
"async": [],
"sync": []
},
"css": {
"async": [],
"sync": []
}
}
},
{
"id": "host:react-dom",
"name": "react-dom",
"version": "18.3.1",
"requiredVersion": "^18.3.1",
"assets": {
"js": {
"async": [],
"sync": []
},
"css": {
"async": [],
"sync": []
}
}
}
],
"remotes": [
{
"federationContainerName": "http://localhost:3110/mf-manifest.json",
"moduleName": "Store",
"alias": "globalStore",
"entry": "*"
},
{
"federationContainerName": "http://localhost:3100/mf-manifest.json",
"moduleName": "App",
"alias": "core",
"entry": "*"
}
],
"exposes": []
}
As far as i know, vite doesnt support circular imports, like remote importing host exposed modules, its one-way - currently rspack/webpack implementations have omnidirectional support
Is a remote trying to import something from host?
No, it shouldn't be.
Host loads GlobalStore and Core Core load GlobalStore GlobalStore loads nothing else
When I was using @originjs/vite-plugin-federation I was able to have core load itself to get the GlobalStore, but I separated it out for this as it was clearly wasn't working, but when I just use remoteEntry.js
without the mf-manifest.json it loads just fine.
@harrisKAsher Could you provide a reproducible example? I plan to resolve the circular references and other related issues that are causing the loop.
For example, I found that @module-federation/bridge-vue3 also causes Vite to call init multiple times. I need to make it more robust.
Multiple initializations aren't a problem. It's a warning, but there's no real danger. Next.js does it too.
It's probably circular remote imports, which I'm not sure if Vite just doesn't work with cyclic host remotes or if it doesn't work with cyclic remotes at all.
Here’s the faulty code; it leads to an infinite loop.
Okay so in our bundlers we track if it was already initialized, so circular remotes do not infinitely initialize
I haven’t yet thought carefully about how to log it without polluting the global scope.
@zhangHongEn Do you still need a reproducible example?
I also export a createContainer function from my packages which just uses webpacks actual mechanics directly for initialization. https://github.com/module-federation/core/blob/main/packages/webpack-bundler-runtime/src/container.ts
we do not need to do it on global scope
// handling circular init calls
var initToken = initTokens[shareScopeName];
if (!initToken)
initToken = initTokens[shareScopeName] = { from: mfInstance.name };
if (initScope.indexOf(initToken) >= 0) return;
initScope.push(initToken);
Note that create container works in other bundlers. This was how remote entry generation in esbuild and I think rollup work
@zhangHongEn Do you still need a reproducible example?
I haven’t reproduced the infinite loop myself, but it indeed needs optimization. No example is needed.
Okay, well I was pretty close to done, so I just finished it up. Here it is in case it helps.
The init token is the main aspect that most miss in the runtime implementation. The init scope is passed through all remotes as another argument so everyone knows what everyone else has so far.
Sorry, not sure I follow, what is the init token? I can't find anything in the docs about such a thing.
Sorry, not sure I follow, what is the init token? I can't find anything in the docs about such a thing.
Speaking to maintainers in thread. Sorry!
Oh, okay. Thought it was a direct response to me. 😅
Also, another thing I am encountering (not sure its related or not) is in a remote app when I import a component from a package (ComponentA) that internally imports another component (ComponentB) from a dependent package, it fails to load the entire federated remote app. If I already import ComponentB in the remote app then everything works. This issue doesn't occur when running I go to the remote apps endpoint and view it outside the federated instance. It also doesn't happen if I do a build and preview it in the Federated Instance. I have tried a bunch of different adjustments to make ComponentA and/or ComponentB shared with the vite config but none that changes anything.
I'm not sure about that one.
Good litmus test is to try it with rspack or rsbuild (our vite-like experience).
If the same setup works with rspack/rsbuild, then it's a problem with vite implementation.
If it doesn't, then it's a bug in our runtime.
Okay, well I was pretty close to done, so I just finished it up. Here it is in case it helps.
Thanks for sharing, I'll copy your example in the repo to show how to do it
I'm not sure about that one.
Good litmus test is to try it with rspack or rsbuild (our vite-like experience).
If the same setup works with rspack/rsbuild, then it's a problem with vite implementation.
If it doesn't, then it's a bug in our runtime.
So I was trying to reproduce this and I cannot do it without one thing: getting from a private npm repository. My organization has an internal package of components to make things uniform across the various web applications we make. Its kind of similar to HeadlessUI. Anyway, that is what is breaking the app, and some of them are pretty simple. Literally some of them are just div's with styles on them. But it seems that if an internal package relies on another internal package that is when it breaks.
My only theory is it is breaking because of how the federation in dev mode can't get the internal package for some reason? Not really sure how to verify that though as I am not that familiar with internal packages. I tried with other packages that are similar such as HeadlessUI but I could not get it to break in the same way.
I was reading intently thus far 👀 waiting to see a solution on this.
Everything @harrisKAsher described is happening to me as well. Line by line. Word for word.
Here's is my example, which is very much similar to his: vite-micro-frontends-react. Like him, I kept things very basic & simple (although my case has 1 parent host & 2 child remotes, no grand-children, 1 child is on build (appears on host's "remotes"), and the other child is dynamically imported).
I will prioritize solving this problem as the top priority when I have time
---- Replied Message ---- | From | @.> | | Date | 11/19/2024 07:20 | | To | module-federation/vite @.> | | Cc | zhn @.>, Mention @.> | | Subject | Re: [module-federation/vite] HMR Does not work (Issue #183) |
I was reading intently thus far 👀 waiting to see a solution on this.
@.*** described is happening to me as well. Line by line. Word for word.
Here's is my example, which is very much similar to his: vite-micro-frontends-react. Like him, I kept things very basic & simple (although my case has 1 parent host & 2 child remotes, no grand-children, 1 child is on build (appears on host's "remotes"), and the other child is dynamically imported).
— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you were mentioned.Message ID: @.***>
So for me to support. I'll require a rspack or webpack based attempt. Then i can help. Otherwise we will need to rely on our community partners who maintain vite to proxy the needs back to me from a runtime perspective.
Core team only allocated resources to
We can wait for @zhangHongEn to take a look and contact Core team, but just letting yall know where my support kicks in. 🥰🥰
Is it like missing css or is there something else like missing JS modules. Missing css would be tailwind tree shake classes it can't see. That can be solved with allow list. If it's missing modules on the other hand. That's something we need to investigate etc
This issue mentions two problems:
Just a heads up. You can contact me on Twitter / bluesky
I have a LLC dedicated to NDA signing operations for such cases. Would allow you to send me a zip of your node modules and all that I can just extract and run without any liabilities on either end.
Pain in the ass but we can pull that never IF it's needed. On my end it's not a problem. Sign a few hundred a year haha 😄
Thanks to @ScriptedAlchemy for providing a solution approach, which allows me to implement it without checking the pack code; the only thing missing is time.
1: Solution is here 2: I haven’t seen the Chrome plugin successfully injecting React
Thanks to @ScriptedAlchemy for providing a solution approach, which allows me to implement it without checking the pack code; the only thing missing is time.
1: Solution is here 2: I haven’t seen the Chrome plugin successfully injecting React
Ahhh time. The great evil of all mankind 🫠
Thanks @ScriptedAlchemy for your core help. this means a lot for this project. Can I suggest to use the official MF public channel Using this channel we avoid lack of alignment.
Alright guys, here's the news. I'll start from the end:
HMR does work for rsbuild
✅
HMR doesn't work for @module-federation/vite
... ❌
I've created a small project that illustrates the 2 bugs: one is the infinite loop, and the other is the HMR not working.
The project: module-federation-with-vite-vs-rsbuild
Steps to reproduce:
master
to a branch called rsbuild
apps/booksMF
, and run:pnpm install
pnpm rsdev
apps/host
, and run:pnpm install
pnpm rsdev
the app will open on http://localhost:3000
booksMF/src/components/App/App.tsx
, and change the text of the h1
from "Vite + React" to whatever, and see that the HMR works properly.host
and books
servers.apps/booksMF
, and run:pnpm dev
apps/host
, and run:pnpm dev
the app will open on http://localhost:3000
The result: an infinite loop! the app will never appear, and you'll see a white screen.
vite.config.ts
of booksMF, and replace manifest: true,
(line 15) with filename: 'remoteEntry.js',
(line 16). Uncomment one and comment out the other. Now, in vite.config.ts
of host, change entry: 'http://localhost:3001/mf-manifest.json',
to entry: 'http://localhost:3001/remoteEntry.js',
.Result: try running both projects now with pnpm dev
again - you'll succeed! But if you'll open up the file booksMF/src/components/App/App.tsx
, and change something in it, you'll find that the HMR doesn't work.
Is it like missing css or is there something else like missing JS modules. Missing css would be tailwind tree shake classes it can't see. That can be solved with allow list. If it's missing modules on the other hand. That's something we need to investigate etc
I am assuming this in response to my importing issue from a private repository for packages? I have realized thats probably a separate issue so I have made a new issue here. But just for the record, there is missing css, but that's not the problem as the components my organization makes uses styled components. So I believe it is missing the module.
Hi, I am trying to migrate from @originjs/vite-plugin-federation to this as it seems better supported and has HMR support. But I cannot get the HMR to work from the remotes (though the app loads). Currently I am just trying to get this set up between 3 different apps.
This is my host/vite.config.ts
This is my core/vite.config.ts
My globalStore/vite.config.ts
The globalStore shouldn't matter as right now I am just trying to get the HMR working between Host and Core and have basically made my App.tsx to look like this in core. I have to keep globalStore in my config though as otherwise it will break as other components need it even though they aren't imported anywhere.
And in Host its this
So as you can see, just about as barebones as it gets, and yet HMR does not work. Though in the console I do see this
[vite] hot updated: /src/App.tsx [client:223:18](http://localhost:3100/@vite/client)
And in the network tab I can see this, which even includes the changes I made to core/App.tsx! Which just baffels me that they are there, yet it will not update them on my host.
Either I am missing or something is broken. If you need further information from me please let me know. Thank you for the support.