remix icon indicating copy to clipboard operation
remix copied to clipboard

Vite plugin: Outdated Optimize Dep errors

Open silvenon opened this issue 2 years ago • 14 comments

Reproduction

I don't think a StackBlitz is appropriate in this case, here's a repo — https://github.com/silvenon/repro/tree/remix-vite, make sure to switch to the remix-vite branch.

It's built on top of your latest Vite template, with added login & logout logic via cookie session storage because I was initially trying to reproduce a logout bug that I was experiencing in Safari (but not in Chrome!) in my app after upgrading to the Vite plugin.

I wasn't able to reproduce that particular one, but I decided to leave in the complexity because I think it's useful for a bug I'm reporting.

System Info

  System:
    OS: macOS 14.3.1
    CPU: (8) arm64 Apple M1 Pro
    Memory: 64.98 MB / 16.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 21.6.2 - ~/.n/bin/node
    Yarn: 1.22.19 - /opt/homebrew/bin/yarn
    npm: 10.2.4 - ~/.n/bin/npm
    pnpm: 8.6.10 - /opt/homebrew/bin/pnpm
    bun: 1.0.23 - ~/.bun/bin/bun
  Browsers:
    Chrome: 121.0.6167.184
    Edge: 121.0.2277.128
    Safari: 17.3.1
  npmPackages:
    @remix-run/dev: ^2.7.0 => 2.7.0 
    @remix-run/node: ^2.7.0 => 2.7.0 
    @remix-run/react: ^2.7.0 => 2.7.0 
    @remix-run/serve: ^2.7.0 => 2.7.0 
    vite: ^5.1.3 => 5.1.3

Used Package Manager

npm

Expected Behavior

Safari has been my default browser for several months now, so after upgrading my Remix app I expected my app's development experience to work similar to how developing regular Remix and Vite apps worked.

Actual Behavior

A quick checks tells me that on Chrome this seems to work fine, but on Safari eventually I continuously start getting "Outdated Optimize Dep" 504 errors in my console with the accompanying "Importing a module script failed" error:

[Error] Failed to load resource: the server responded with a status of 504 (Outdated Optimize Dep) (react_jsx-dev-runtime.js, line 0)
[Error] Unhandled Promise Rejection: TypeError: Importing a module script failed.
[Error] Failed to load resource: the server responded with a status of 504 (Outdated Optimize Dep) (@remix-run_react.js, line   0)
[Error] Failed to load resource: the server responded with a status of 504 (Outdated Optimize Dep) (react.js, line 0)
[Error] Failed to load resource: the server responded with a status of 504 (Outdated Optimize Dep) (react-dom_client.js, line   0)

These errors break client-side JS, most notably HMR stops working.

One way to get them to show up is to start one Remix Vite app, stop it, and start another one. Both have to use the same port. This quirk does not happen with regular Vite apps, I checked, that's why I'm reporting it here.

The only way I found to make these errors go away immediately is to go to Safari Settings → Privacy → Manage Website Data and clear data from "localhost". Otherwise they stay even if you restart the dev server, if you delete the .cache directory or run npm ci.

That's as far as I got, hopefully that helps!

silvenon avatar Feb 20 '24 09:02 silvenon

I recommended trying to cause the 504 errors by messing around with CSS setup and impports because I have a feeling they might be connected, but I'm not sure, I haven't found consistent steps to make them appear, I just know that they start happening pretty soon after I start development.

silvenon avatar Feb 20 '24 18:02 silvenon

I realized that HMR breaks because of the errors, it works until they start appearing, so I edited my issue description to focus just on them.

silvenon avatar Feb 20 '24 18:02 silvenon

To reproduce the issue: start one Remix Vite app, and then another one on the same port. You should be seeing the errors. This quirk does NOT happen with regular Vite apps. (Updated the PR description.)

I also figured out how to get the errors to go away: I need to clear "localhost" data under Safari Settings → Privacy → Manage Website Data.

I have to say it's a relief knowing both how to reproduce the errors and how to clear them 😮‍💨

Screenshot 2024-02-20 at 23 06 20

silvenon avatar Feb 20 '24 22:02 silvenon

I've been encountering this as well. When trying to debug it, I found that the problem seemed to be the rel="preload" tags for eg entry.client.tsx.

It seems that the preload tag makes Safari very eager in its caching (which might by according to spec?), which means that the old version of the scripts keeps getting used. The 504's happen cause those old files point to old (versions of) dependencies, as shown by the old hashes in the urls.

I imagine the solution is either adding hashes to the preloaded urls, or allowing disabling the preload in dev.

kazdegroot avatar Feb 23 '24 14:02 kazdegroot

As a workaround got it working by replacing the modulepreload on the html in entry.server.ts like this:

export default function handleRequest(...) {
...
let html = renderToString(
  <RemixServer context={remixContext} url={request.url} />,
)
html = html.replace(/rel\=\"modulepreload\"/g, '')
...

No sure how that would work for the streaming api but can probably do something similar.

gatzjames avatar Feb 23 '24 16:02 gatzjames

It seems that the preload tag makes Safari very eager in its caching (which might by according to spec?), which means that the old version of the scripts keeps getting used.

The 504's happen cause those old files point to old (versions of) dependencies, as shown by the old hashes in the urls.

Thanks for expanding on this, @kazdegroot! That makes sense, because errors start happening during development as well, making development on Safari basically impossible, because every now and then I have to keep clearing the cache.

silvenon avatar Feb 23 '24 16:02 silvenon

As a workaround got it working by replacing the modulepreload on the html in entry.server.ts like this:

export default function handleRequest(...) {
...
let html = renderToString(
  <RemixServer context={remixContext} url={request.url} />,
)
html = html.replace(/rel\=\"modulepreload\"/g, '')
...

No sure how that would work for the streaming api but can probably do something similar.

Good idea. Haven't actually tested with streaming, but am using what looks like a streaming enabled entry.server.ts, and this seems to solve my issue:

import replace from "stream-replace-string";
...
function handleBrowserRequest(...) {
  ...
  onShellReady() {
    ...
    const body = new PassThrough().pipe(
      replace('rel="modulepreload"', "")
    );
    const stream = createReadableStreamFromReadable(body);
    ...

(which is basically the same, using a library that does string replacement in streams)

kazdegroot avatar Mar 01 '24 22:03 kazdegroot

Confirming I'm seeing this behavior while developing in Arc/Brave, which basically breaks the DX completely, and that removing the modulepreload in the way @kazdegroot noted resolves the issue. I'm running a single remix 2.8.1 express app updating using the official vite instructions.

ianserlin avatar Mar 10 '24 07:03 ianserlin

New to vite here, but it also seems like disabling modulePreload when creating the vite server in my ./server.mjs helps with development stability, whereas without it seems that I often get errors the first first time I click to a new screen after dev server start, which causes a page reload and canceled navigation:

const viteDevServer =
    process.env.NODE_ENV === "production"
      ? undefined
      : await import("vite").then((vite) =>
          vite.createServer({
            server: { middlewareMode: true },
            build: {
              modulePreload: false,
            },
          })
        );

ianserlin avatar Mar 12 '24 06:03 ianserlin

I also figured out how to get the errors to go away: I need to clear "localhost" data under Safari Settings → Privacy → Manage Website Data.

Wow. Thanks for sharing this. I was pounding my head for the last 20 minutes trying to bisect my changes to figure out the problem with my Remix project. This was the fix I needed.

khera avatar May 05 '24 17:05 khera

I have had this issue for a long time too, I was able to solve it by reloading using Option + Command + R, which should force clear the website data.

sergiodxa avatar May 06 '24 18:05 sergiodxa

So it's Option instead of Shift on Safari 😮 I didn't know that, thanks!

silvenon avatar May 06 '24 18:05 silvenon

Yeah Shift + Command + R in Safari enables the Reader Mode

sergiodxa avatar May 06 '24 21:05 sergiodxa

Is this the same issue as described here: https://github.com/remix-run/remix/discussions/8917 ?

hhsl avatar May 23 '24 14:05 hhsl

We are encountering this as well, only on Safari. @silvenon Was your long term solve to just not dev on Safari? Chromium browsers are unaffected by this for us.

nlewis84 avatar Aug 09 '24 22:08 nlewis84

Yes. But I find developing in Chrome nicer anyway because of its developer tools, so it isn't difficult to keep in mind.

But it would be nice if we didn't have to, people should be able do develop in every modern browser.

silvenon avatar Aug 10 '24 09:08 silvenon

🤖 Hello there,

We just published version 2.12.0-pre.0 which involves this issue. If you'd like to take it for a test run please try it out and let us know what you think!

Thanks!

github-actions[bot] avatar Sep 05 '24 14:09 github-actions[bot]

🤖 Hello there,

We just published version 2.12.0 which involves this issue. If you'd like to take it for a test run please try it out and let us know what you think!

Thanks!

github-actions[bot] avatar Sep 09 '24 17:09 github-actions[bot]