Skip to content

Commit 53ecc44

Browse files
authored
Update refresh utils for Remix support (#191)
1 parent a847abe commit 53ecc44

File tree

3 files changed

+33
-10
lines changed

3 files changed

+33
-10
lines changed

playground/hmr/__tests__/hmr.spec.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ test("HMR invalidate", async ({ page }) => {
3535
// Edit export
3636
editFile("src/TitleWithExport.tsx", ["React", "React!"]);
3737
await waitForLogs(
38-
"[vite] invalidate /src/TitleWithExport.tsx: Could not Fast Refresh. Learn more at https://github.com/vitejs/vite-plugin-react-swc#consistent-components-exports",
38+
'[vite] invalidate /src/TitleWithExport.tsx: Could not Fast Refresh ("framework" export is incompatible). Learn more at https://github.com/vitejs/vite-plugin-react-swc#consistent-components-exports',
3939
"[vite] hot updated: /src/App.tsx",
4040
);
4141
await expect(page.locator("h1")).toHaveText("Vite * React!");

src/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ RefreshRuntime.__hmr_import(import.meta.url).then((currentExports) => {
162162
RefreshRuntime.registerExportsForReactRefresh("${id}", currentExports);
163163
import.meta.hot.accept((nextExports) => {
164164
if (!nextExports) return;
165-
const invalidateMessage = RefreshRuntime.validateRefreshBoundaryAndEnqueueUpdate(currentExports, nextExports);
165+
const invalidateMessage = RefreshRuntime.validateRefreshBoundaryAndEnqueueUpdate("${id}", currentExports, nextExports);
166166
if (invalidateMessage) import.meta.hot.invalidate(invalidateMessage);
167167
});
168168
});

src/refresh-runtime.js

+31-8
Original file line numberDiff line numberDiff line change
@@ -581,41 +581,64 @@ function debounce(fn, delay) {
581581
};
582582
}
583583

584-
const enqueueUpdate = debounce(performReactRefresh, 16);
584+
const hooks = [];
585+
window.__registerBeforePerformReactRefresh = (cb) => {
586+
hooks.push(cb);
587+
};
588+
const enqueueUpdate = debounce(async () => {
589+
if (hooks.length) await Promise.all(hooks.map((cb) => cb()));
590+
performReactRefresh();
591+
}, 16);
585592

586593
export function validateRefreshBoundaryAndEnqueueUpdate(
594+
id,
587595
prevExports,
588596
nextExports,
589597
) {
590-
if (!predicateOnExport(prevExports, (key) => key in nextExports)) {
598+
const ignoredExports = window.__getReactRefreshIgnoredExports?.({ id }) ?? [];
599+
if (
600+
predicateOnExport(
601+
ignoredExports,
602+
prevExports,
603+
(key) => key in nextExports,
604+
) !== true
605+
) {
591606
return "Could not Fast Refresh (export removed)";
592607
}
593-
if (!predicateOnExport(nextExports, (key) => key in prevExports)) {
608+
if (
609+
predicateOnExport(
610+
ignoredExports,
611+
nextExports,
612+
(key) => key in prevExports,
613+
) !== true
614+
) {
594615
return "Could not Fast Refresh (new export)";
595616
}
596617

597618
let hasExports = false;
598619
const allExportsAreComponentsOrUnchanged = predicateOnExport(
620+
ignoredExports,
599621
nextExports,
600622
(key, value) => {
601623
hasExports = true;
602624
if (isLikelyComponentType(value)) return true;
603625
return prevExports[key] === nextExports[key];
604626
},
605627
);
606-
if (hasExports && allExportsAreComponentsOrUnchanged) {
628+
if (hasExports && allExportsAreComponentsOrUnchanged === true) {
607629
enqueueUpdate();
608630
} else {
609-
return "Could not Fast Refresh. Learn more at https://github.com/vitejs/vite-plugin-react-swc#consistent-components-exports";
631+
return `Could not Fast Refresh ("${allExportsAreComponentsOrUnchanged}" export is incompatible). Learn more at https://github.com/vitejs/vite-plugin-react-swc#consistent-components-exports`;
610632
}
611633
}
612634

613-
function predicateOnExport(moduleExports, predicate) {
635+
function predicateOnExport(ignoredExports, moduleExports, predicate) {
614636
for (const key in moduleExports) {
615637
if (key === "__esModule") continue;
638+
if (ignoredExports.includes(key)) continue;
616639
const desc = Object.getOwnPropertyDescriptor(moduleExports, key);
617-
if (desc && desc.get) return false;
618-
if (!predicate(key, moduleExports[key])) return false;
640+
if (desc && desc.get) return key;
641+
if (!predicate(key, moduleExports[key])) return key;
619642
}
620643
return true;
621644
}

0 commit comments

Comments
 (0)