node-mf
node-mf copied to clipboard
SSR stuck after remote rebuilds
Hi there, thank you for the work you've done putting this together. I was just wondering if you've run into issues where your Next.js app gets "stuck" with an outdated remote via SSR?
For example:
- website 1 (Next.js) consumes a remote
- website 2 (remote) exposes a module
Scenario:
- Both sites build / deploy
- Website 2 makes a change to its exposed component, then rebuilds / redeploys
- Changes are not reflected on website 1 via SSR (changes become visible on client - after some flickering)
Hi @Kinbaum , thanks for raising the issue. I'll take a look, didn't test my solution with that conditions. Thanks.
Hi @Kinbaum, unfortunately I cann't reproduce the issue with node-mf-example. Can you bring more details on your projects setup? What is the http status you receive when fetch the nextjs page?
Hey, I have created a reproduction scenario using node-mf-example
Initial build
- Run
yarn build && yarn startin bothhostandremoteLib - You will see everything working as expected
Modifying the remote
Do not touch or modify the host. This should be left running.
- Now in
remoteLibkill the application and change the button text - Run
yarn build && yarn startagain to build the remote
Observing changes in the host (use incognito mode in Chrome)
- Go back to the host application.
- On the client side we should see
Some new button - However, on the server side, we will still see
Hey, I'm a smart buttonas SSR is stuck and does not update between remote builds.
Right-click and select View page source to see the SSR'd version of the page.
bump
This is a very complex problem to try and solve. Hot reloading servers is tricky since webpack already required the chunk from another build, it wont redownload a chunk it already has.
There are ways around this though.
- you can use federation on a custom express server to import the next() route handler. This would allow you to purge require cache, flush express route stack, and re-instantiate webpack in a empty closure, thus requiring webpack to re-stream chunks from other remotes
- Use a worker thread. Run the next middleware inside a worker so you can dispose of that thread and start another worker which cleans the "stuck" module problem in a similar way a process restart would
- have a reload endpoint that kills the process and then passes the argv back to a spawn command
Some of these patterns might be best used on a stale while revalidate loop or timer so that the current page load is not slowed down by needing to restream modules
My solution was an endpoint on my app that receives other remote apps updates so I can flush require cache. As I use the promise remote with node-mf, the app stream the new remote app uri and avoid to get stuck.
Okay so I’ve close to releasing a large update to my groups internal stream plugin.
I’m using something that calculates the collective hash of the remotes. During invocations, I’ll load remotes again in the background and calculate the hash. If it mismatches the current hash, I set a marker that waits for server to close current requests and performs a hot reload.
I’m looking at using vm.script, shared array buffer, and v8 isolates as a way to protect the main thread from pollution.
Has anyone else noticed nested remote modules being skipped on first invocations?