Vite plugin: Outdated Optimize Dep errors
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!
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.
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.
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 😮💨
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.
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.
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.
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)
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.
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,
},
})
);
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.
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.
So it's Option instead of Shift on Safari 😮 I didn't know that, thanks!
Yeah Shift + Command + R in Safari enables the Reader Mode
Is this the same issue as described here: https://github.com/remix-run/remix/discussions/8917 ?
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.
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.
🤖 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!
🤖 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!