|
3 | 3 |
|
4 | 4 | import type {PluginOption} from "vite" |
5 | 5 |
|
| 6 | +const REACT_ROUTER_HMR_RUNTIME_ID = "virtual:react-router/hmr-runtime" |
| 7 | +const REACT_ROUTER_FULL_RELOAD_PATH = "/__frontmatter-hmr-fix/full-reload" |
| 8 | +const reactRouterMissingRouteModuleUpdateError = |
| 9 | + /^(\s*)throw Error\(\s*`\[react-router:hmr\] No module update found for route \$\{route\.id\}`,\s*\);/m |
| 10 | + |
6 | 11 | /** |
7 | 12 | * Options for the {@link frontmatterHmrPlugin}. |
8 | 13 | */ |
@@ -37,8 +42,40 @@ export function frontmatterHmrPlugin( |
37 | 42 | ): PluginOption { |
38 | 43 | const {exportName = "frontmatter"} = opts |
39 | 44 | return { |
| 45 | + configureServer(server) { |
| 46 | + server.middlewares.use( |
| 47 | + REACT_ROUTER_FULL_RELOAD_PATH, |
| 48 | + (req, res, next) => { |
| 49 | + if (req.method !== "POST") { |
| 50 | + next() |
| 51 | + return |
| 52 | + } |
| 53 | + |
| 54 | + server.ws.send({type: "full-reload"}) |
| 55 | + res.statusCode = 204 |
| 56 | + res.end() |
| 57 | + }, |
| 58 | + ) |
| 59 | + }, |
40 | 60 | name: "frontmatter-hmr-fix", |
41 | | - transform(code: string) { |
| 61 | + transform(code: string, id: string) { |
| 62 | + if (id.includes(REACT_ROUTER_HMR_RUNTIME_ID)) { |
| 63 | + // React Router sends route metadata updates for edited route files even |
| 64 | + // when the browser has not imported that route module yet. In that |
| 65 | + // cold-route case there is no module accept callback to populate |
| 66 | + // __reactRouterRouteModuleUpdates, so the runtime needs to reload |
| 67 | + // instead of throwing. |
| 68 | + return code.replace( |
| 69 | + reactRouterMissingRouteModuleUpdateError, |
| 70 | + (_match, indent: string) => |
| 71 | + [ |
| 72 | + `${indent}console.debug(\`[react-router:hmr] No module update found for route \${route.id}\`);`, |
| 73 | + `${indent}void fetch("${REACT_ROUTER_FULL_RELOAD_PATH}", {method: "POST"}).catch(() => window.location.reload());`, |
| 74 | + `${indent}return;`, |
| 75 | + ].join("\n"), |
| 76 | + ) |
| 77 | + } |
| 78 | + |
42 | 79 | if (code.includes(`export const ${exportName}`)) { |
43 | 80 | // cheat `isLikelyComponentType` |
44 | 81 | // https://github.com/facebook/react/blob/f5af92d2c47d1e1f455faf912b1d3221d1038c37/packages/react-refresh/src/ReactFreshRuntime.js#L717-L723 |
|
0 commit comments