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

Closed
4 tasks done
ngbrown opened this issue Apr 26, 2024 · 5 comments · Fixed by #17891
Closed
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:

@itsdouges
Copy link

itsdouges commented Sep 26, 2024

Hello! My users are running into this problem unfortunately when using Triplex (a visual editor, see: https://triplex.dev). Vite is used for the local development backend.

Triplex is available as a standalone Electron app as well as an extension inside VS Code. I've gotten feedback around the editor becoming unresponsive after their OS sleeps, which e.g. happens immediately when closing a macOS lapto. When this happens they're forced to close the editor and re-open.

In the Electron app I've been able to work around the problem by forcing headers onto all web server responses. When the OS goes to sleep and is woken up they can continue their session right where they left off!

Unfortunately I don't have this flexibility in the VS Code extension, so having the ability to set the headers on the HMR response would be great.

I saw the hmr.server option and you've spoke about it earlier in this issue — I'll see if I can use and set the headers for the response myself though, will report back.

@github-actions github-actions bot locked and limited conversation to collaborators Nov 9, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants