node-mf icon indicating copy to clipboard operation
node-mf copied to clipboard

SSR stuck after remote rebuilds

Open Kinbaum opened this issue 4 years ago • 7 comments

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)

Kinbaum avatar Aug 05 '21 17:08 Kinbaum

Hi @Kinbaum , thanks for raising the issue. I'll take a look, didn't test my solution with that conditions. Thanks.

telenko avatar Aug 07 '21 09:08 telenko

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?

telenko avatar Aug 22 '21 11:08 telenko

Hey, I have created a reproduction scenario using node-mf-example

Initial build

  1. Run yarn build && yarn start in both host and remoteLib
  2. You will see everything working as expected

Modifying the remote

Do not touch or modify the host. This should be left running.

  1. Now in remoteLib kill the application and change the button text
  2. Run yarn build && yarn start again to build the remote
Screen Shot 2021-08-22 at 2 57 26 PM

Observing changes in the host (use incognito mode in Chrome)

  1. Go back to the host application.
  2. On the client side we should see Some new button
  3. However, on the server side, we will still see Hey, I'm a smart button as SSR is stuck and does not update between remote builds.
Screen Shot 2021-08-22 at 3 02 52 PM

Right-click and select View page source to see the SSR'd version of the page.

Screen Shot 2021-08-22 at 3 03 06 PM

Kinbaum avatar Aug 22 '21 19:08 Kinbaum

bump

wibed avatar Aug 27 '21 07:08 wibed

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.

  1. 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
  2. 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
  3. 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

ScriptedAlchemy avatar Feb 07 '22 20:02 ScriptedAlchemy

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.

noreiller avatar Feb 07 '22 20:02 noreiller

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?

ScriptedAlchemy avatar Feb 18 '22 05:02 ScriptedAlchemy