originjs / vite-plugin-federation

Module Federation for vite & rollup
Other
2.39k stars 242 forks source link

Require imports do not work if federation is used #454

Open dziedrius opened 1 year ago

dziedrius commented 1 year ago

We've noticed that after we've used federation plugin, one part of our application started to fail with:

__federation_shared_react-dom.js:233 TypeError: Cannot read properties of null (reading 'useRef')
    at react_production_min.useRef (__federation_shared_react.js:67:402)
    at useReactMediaRecorder (__federation_expose_Button-95782a6b.js:6598:45)
    at ReactMediaRecorder (__federation_expose_Button-95782a6b.js:6844:26)
    at Xh (__federation_shared_react-dom.js:211:137)
    at Wk (__federation_shared_react-dom.js:334:339)
    at Vk (__federation_shared_react-dom.js:324:393)
    at Uk (__federation_shared_react-dom.js:324:322)
    at Jk (__federation_shared_react-dom.js:324:181)
    at Ok (__federation_shared_react-dom.js:315:88)
    at Hk (__federation_shared_react-dom.js:312:432)

We saw similar complaints as open issues, but I'm not sure if our issue has the same root cause, hence opening as separate one, if we will see that they converge, we might close one of the issues as duplicate.

It seems, that if remote is importing component that is using require, like this:

// taken from compiled file: https://www.npmjs.com/package/react-media-recorder?activeTab=code
// react-media-recorder/lib/index.js
var react_1=require("react");

it works fine using in vite directly, but fails if used through module federation.

To isolate the issue, I took react-vite example from vite-plugin-federation repo master and adjusted a bit to match our situation, added dependency to failing component:

Index: packages/examples/react-vite/remote/package.json
@@ -11,7 +11,8 @@
   },
   "dependencies": {
     "react": "^18.2.0",
-    "react-dom": "^18.2.0"
+    "react-dom": "^18.2.0",
+    "react-media-recorder": "1.6.6"
   },
   "devDependencies": {
     "@types/react": "^18.0.17",

and added that component to the remote button:

Index: packages/examples/react-vite/remote/src/components/Button.jsx
@@ -1,5 +1,6 @@

 import "./Button.css"
+import { ReactMediaRecorder } from "react-media-recorder";

 import { useState } from "react"

@@ -8,6 +9,17 @@
   return (
     <div>
       <button id='click-btn' className='shared-btn' onClick={() => setState((s) => s + 1)}>Click me: {state}</button>
+        <ReactMediaRecorder
+            video
+            render={({status, startRecording, stopRecording, mediaBlobUrl}) => (
+                <div>
+                    <p>{status}</p>
+                    <button onClick={startRecording}>Start Recording</button>
+                    <button onClick={stopRecording}>Stop Recording</button>
+                    <video src={mediaBlobUrl} controls autoPlay loop/>
+                </div>
+            )}
+        />   
     </div>
   )
 }

So going directly to remote, everything works as expected, going to host it fails to load due react error.

Any ideas if this can by somehow fixed by adjusting configuration or that is a bug/missing feature in vite-plugin-federation, if yes, would it be hard to fix it?

Currently this is a showstopper for us, even if we possibly could rewrite component used in example to avoid the issue, I think the situation is too common and sooner or later we will face situation were it will not make sense to rewrite and we will be forced to switch back to webpack :(

Versions

julianps commented 1 year ago

Hey, I had the same issue this morning and in my case the issue was caused by the host using a custom hook from the remote module. The custom hook (defined in the remote) imports smth from redux-oidc. I changed the vite.config.js in both modules to contain redux-oidc like below which fixed the error for me. Hope that helps for you too.

shared: ['react', 'react-dom', 'react-redux']

mariojfduarte commented 1 year ago

facing the same issue

"@originjs/vite-plugin-federation": "^1.2.3", "@vitejs/plugin-react": "^3.1.0", "autoprefixer": "^10.4.13", "compression": "^1.7.4", "cors": "^2.8.5", "express": "^4.18.2", "postcss-import": "^15.1.0", "tailwindcss": "^3.2.7", "vite": "^4.4.2"

dziedrius commented 1 year ago

@julianps, thanks, suggested workaround worked for me too, probably will use temporary.

But in general it is a ugly workaround, as it couples host and remote and whole module federation purpose is to decouple :) Hopefully there will be proper way to handle this.

sOstrovsky commented 2 months ago

@julianps thanks man, works for me too!