vercel / next.js

The React Framework
https://nextjs.org
MIT License
127.04k stars 27k forks source link

HMR not working with an assetPrefix that is a relative path #41377

Open jordanmnunez opened 2 years ago

jordanmnunez commented 2 years ago

Verify canary release

Provide environment information


    Operating System:
      Platform: linux
      Arch: x64
      Version: #29~20.04.1-Ubuntu SMP Fri Jan 7 12:24:31 UTC 2022
    Binaries:
      Node: 16.15.1
      npm: 8.11.0
      Yarn: 1.22.17
      pnpm: N/A
    Relevant packages:
      next: 12.2.3
      eslint-config-next: 12.2.3
      react: 18.2.0
      react-dom: 18.2.0

warn  - Latest canary version not detected, detected: "12.2.3", newest: "12.3.2-canary.26".
        Please try the latest canary version (`npm install next@canary`) to confirm the issue still exists before creating a new issue.
        Read more - https://nextjs.org/docs/messages/opening-an-issue

What browser are you using? (if relevant)

No response

How are you deploying your application? (if relevant)

next dev running locally, served via nginx reverse proxy

Describe the Bug

HMR stopped working after I added a relative path assetPrefix.

In my org, we have unlimited of developer servers that could have any subdomain: sally.devbox.com, varoon.devbox.com, bob.devbox.com. I want to use assetPrefix to namespace the assets to a particular package of next.js.

So, I add assetPrefix:/public-site-assets/tonext.config.js`.

The rendered templates behave as expected way: On sally's box they point to sally.devbox.com/public-site-assets/.. On bob's box they point to bob.devbox.com/public-site-assets/.. On varoon's box they point to varoon.devbox.com/public-site-assets/..

However, hot module reloading has stopped working. In the console I see the following warning: nginx WebSocket is closed before the connection is established. It isn't an error. It appears to be timing out.

My nginx servers pass along the proper http upgrade headers to support wss. It was working before adding the prefix.

After doing some digging, I found the PR that first fixed HMR for assetPrefixes: https://github.com/vercel/next.js/pull/30632.

However, I notice something odd when reading through the code. The hmr logic is expected the paths to either include a protocol or be absolute. i.e., It is always prepending a slash if there is no protocol. My guess is that the request is being sent off into the ether, causing the timeout.

I proved my hypothesis by hardcoding the assetPrefix to the server address that I am using: sally.devbox.com/public-site-assets/. Bingo, Bango; it works again.

It looks like this code is still in the main branch: https://github.com/vercel/next.js/pull/30632/files#diff-503b31fa14e16da2eff70176a73da5d351caaa0f714f1ad67e61590024568801R494-R496

Expected Behavior

HMR should support both absolute and relative paths.

Link to reproduction

https://codesandbox.io/s/boring-dawn-1jcue5

To Reproduce

add a relative path to assetPrefix in next.config.js

gligoran commented 2 years ago

Hi.

I'm experiencing the same thing with a brand new setup of Next 13.

We have a very similar setup to @jordanmnunez with per-developer root domains and assetPrefix set up.

Our current workaround is to use environment variables to determine if we're running in dev mode and then set the assetPrefix with domain included. To extend on @jordanmnunez example, this would be:

  assetPrefix: process.env.NODE_ENV === 'development' ? `http://${process.env.USER}.devbox.com/public-site-assets/` : '/public-site-assets/',