Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy on hmr dev server #16536

Open
4 tasks done
ngbrown opened this issue Apr 26, 2024 · 4 comments
Open
4 tasks done

Comments

@ngbrown
Copy link

ngbrown commented Apr 26, 2024

Description

Like #3909 but for the HMR dev server. During development I have the COEP header with a value of require-corp to access certain features like SharedArrayBuffer objects or Performance.now() with unthrottled timers. (cross-origin isolated features).

From MDN:

Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Opener-Policy: same-origin

The problem is that when the server is restarting, the HMR WebSocket connection switches to polling on the HMR port ("[vite] server connection lost. polling for restart..."). However, the browser is giving this error:

The resource at “http://localhost:8002/” was blocked due to its Cross-Origin-Resource-Policy header (or lack thereof). See https://developer.mozilla.org/docs/Web/HTTP/Cross-Origin_Resource_Policy_(CORP)

The resource never connects and the page doesn't automatically reload. I have to manually reload the page so it can establish the WebSocket connection. This also happens when vite.config.ts changes.

I tried setting the server.headers option, but it doesn't affect the HMR server endpoint. (This is an Remix app hosted in Express, so not actually using the Vite dev server, just the HMR server).

The server.hmr.server option seems to take a class instance and there is no server.hmr.headers option.

Suggested solution

Add a server.hmr.headers option like was implemented in #5580.

The headers I need to set would look like this:

{
  server: {
    hmr: {
      headers: {
        "cross-origin-resource-policy": "cross-origin",
      },
    },
  },
}

Alternative

I could remove the Cross-Origin-Embedder-Policy and Cross-Origin-Opener-Policy headers while in development, but the cross-origin isolated browser features would be disabled.

Additional context

No response

Validations

@hi-ogawa
Copy link
Collaborator

hi-ogawa commented Apr 27, 2024

This is an Remix app hosted in Express, so not actually using the Vite dev server, just the HMR server

Can you provide a reproduction to show how the issue look like?
It's not entirely clear that how you setup coop/coep headers on Remix express, so providing that would probably help.

You might be able to avoid this issue by passing your own node server to server.hmr.server (for example, something like I suggested for Remix Vite https setup long time ago https://github.com/hi-ogawa/test-remix-vite-express-https/blob/06da66d41950b8b0b3014f4f841d07e6fcffc7bf/server.mjs#L34), but I might be totally misunderstanding the issue.

Starting from their express template https://github.com/remix-run/remix/tree/main/templates/express, this is what I imagined would help https://stackblitz.com/edit/github-1jwsyy?file=server.js

@ngbrown
Copy link
Author

ngbrown commented Apr 27, 2024

Here is a demonstration of the way I setup my headers and how the problem manifests: https://github.com/ngbrown/remix-vite-16536

@ngbrown
Copy link
Author

ngbrown commented Apr 27, 2024

@hi-ogawa - I tried to change the server.js file with the way you passed server into the Vite hmr property, it does work by re-using the same server instance as the rest of the application, but I had a few questions:

  • Wouldn't it be better to have a separate port like HMR is expected to have? Sharing the same port is how the default Remix template works.
  • Since this is hosted at the same port as the rest of the application. How would it work if the application had it's own WebSocket connection that it wanted to maintain? Wouldn't they conflict?

I've updated my suggested solution with the headers I would like to set, assuming the HMR server is on a different port.

@hi-ogawa
Copy link
Collaborator

Since this is hosted at the same port as the rest of the application. How would it work if the application had it's own WebSocket connection that it wanted to maintain? Wouldn't they conflict?

Yeah, that could be a concern, but maybe it's still possible to get around by setting server.hmr.path to not conflict with your app's websocket path?

hmrBase = path.posix.join(hmrBase, hmrPath)


I tested your reproduction and I can confirm the issue, but it feels like a minor paper cut with very specific conditions.
Also I wonder if this is more like a problem of Vite's client-side websocket failure robustness. See for example:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants