Skip to content

Commit

Permalink
fix(vite): fix Fast Refresh load error when using defer (#7842)
Browse files Browse the repository at this point in the history
Signed-off-by: Marc MacLeod <[email protected]>
Co-authored-by: Mark Dalgleish <[email protected]>
  • Loading branch information
Marc MacLeod and markdalgleish authored Nov 2, 2023
1 parent d1c93a1 commit b4e2993
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 18 deletions.
5 changes: 5 additions & 0 deletions .changeset/sharp-kids-bake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@remix-run/dev": patch
---

Fix React Fast Refresh error on load when using `defer` in Vite dev server
39 changes: 31 additions & 8 deletions integration/vite-dev-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,20 +59,28 @@ test.describe("Vite dev", () => {
}
`,
"app/routes/_index.tsx": js`
import { useState, useEffect } from "react";
import { Suspense } from "react";
import { defer } from "@remix-run/node";
import { Await, useLoaderData } from "@remix-run/react";
export function loader() {
let deferred = new Promise((resolve) => {
setTimeout(() => resolve(true), 1000)
});
return defer({ deferred });
}
export default function IndexRoute() {
const [mounted, setMounted] = useState(false);
useEffect(() => {
setMounted(true);
}, []);
const { deferred } = useLoaderData<typeof loader>();
return (
<div id="index">
<h2 data-title>Index</h2>
<input />
<p data-mounted>Mounted: {mounted ? "yes" : "no"}</p>
<p data-hmr>HMR updated: no</p>
<Suspense fallback={<p data-defer>Defer finished: no</p>}>
<Await resolve={deferred}>{() => <p data-defer>Defer finished: yes</p>}</Await>
</Suspense>
</div>
);
}
Expand Down Expand Up @@ -161,12 +169,19 @@ test.describe("Vite dev", () => {
});

test("renders matching routes", async ({ page }) => {
let pageErrors: unknown[] = [];
page.on("pageerror", (error) => pageErrors.push(error));

await page.goto(`http://localhost:${devPort}/`, {
waitUntil: "networkidle",
});

// Ensure no errors on page load
expect(pageErrors).toEqual([]);

await expect(page.locator("#index [data-title]")).toHaveText("Index");
await expect(page.locator("#index [data-mounted]")).toHaveText(
"Mounted: yes"
await expect(page.locator("#index [data-defer]")).toHaveText(
"Defer finished: yes"
);

let hmrStatus = page.locator("#index [data-hmr]");
Expand All @@ -188,13 +203,21 @@ test.describe("Vite dev", () => {
await page.waitForLoadState("networkidle");
await expect(hmrStatus).toHaveText("HMR updated: yes");
await expect(input).toHaveValue("stateful");

// Ensure no errors after HMR
expect(pageErrors).toEqual([]);
});

test("handles multiple set-cookie headers", async ({ page }) => {
let pageErrors: Error[] = [];
page.on("pageerror", (error) => pageErrors.push(error));

await page.goto(`http://localhost:${devPort}/set-cookies`, {
waitUntil: "networkidle",
});

expect(pageErrors).toEqual([]);

// Ensure we redirected
expect(new URL(page.url()).pathname).toBe("/get-cookies");

Expand Down
32 changes: 22 additions & 10 deletions packages/remix-dev/vite/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ let serverManifestId = VirtualModule.id("server-manifest");
let browserManifestId = VirtualModule.id("browser-manifest");
let remixReactProxyId = VirtualModule.id("remix-react-proxy");
let hmrRuntimeId = VirtualModule.id("hmr-runtime");
let injectHmrRuntimeId = VirtualModule.id("inject-hmr-runtime");

const normalizePath = (p: string) => {
let unixPath = p.replace(/[\\/]+/g, "/").replace(/^([a-zA-Z]+:|\.\/)/, "");
Expand Down Expand Up @@ -689,21 +690,32 @@ export const remixVitePlugin: RemixVitePlugin = (options = {}) => {
'export const LiveReload = process.env.NODE_ENV !== "development" ? () => null : ',
'() => createElement("script", {',
' type: "module",',
" suppressHydrationWarning: true,",
" dangerouslySetInnerHTML: { __html: `",
` import RefreshRuntime from "${VirtualModule.url(
hmrRuntimeId
)}"`,
" RefreshRuntime.injectIntoGlobalHook(window)",
" window.$RefreshReg$ = () => {}",
" window.$RefreshSig$ = () => (type) => type",
" window.__vite_plugin_react_preamble_installed__ = true",
" `}",
" async: true,",
` src: "${VirtualModule.url(injectHmrRuntimeId)}"`,
"});",
].join("\n");
}
},
},
{
name: "remix-inject-hmr-runtime",
enforce: "pre",
resolveId(id) {
if (id === injectHmrRuntimeId)
return VirtualModule.resolve(injectHmrRuntimeId);
},
async load(id) {
if (id !== VirtualModule.resolve(injectHmrRuntimeId)) return;

return [
`import RefreshRuntime from "${hmrRuntimeId}"`,
"RefreshRuntime.injectIntoGlobalHook(window)",
"window.$RefreshReg$ = () => {}",
"window.$RefreshSig$ = () => (type) => type",
"window.__vite_plugin_react_preamble_installed__ = true",
].join("\n");
},
},
{
name: "remix-hmr-runtime",
enforce: "pre",
Expand Down

0 comments on commit b4e2993

Please sign in to comment.