Skip to content

Commit e2acd9f

Browse files
authored
Update invalid exports messaging (#13049)
1 parent 95fd01d commit e2acd9f

File tree

4 files changed

+36
-29
lines changed

4 files changed

+36
-29
lines changed

.changeset/weak-mayflies-lie.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@react-router/dev": patch
3+
---
4+
5+
[REMOVE] Update invalid route export messages

docs/how-to/pre-rendering.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,3 +149,14 @@ sirv-cli build/client --single index.html
149149
# If you pre-rendered the `/` route
150150
sirv-cli build/client --single __spa-fallback.html
151151
```
152+
153+
### Invalid Exports
154+
155+
When pre-rendering with `ssr:false`, React Router will error at build time if you have invalid exports to help prevent some mistakes that can be easily overlooked.
156+
157+
- `headers`/`action` functions are prohibited in all routes because there will be no runtime server on which to run them
158+
- When using `ssr:false` without a `prerender` config (SPA Mode), a `loader` is permitted on the root route only
159+
- When using `ssr:false` with a `prerender` config, a `loader` is permitted on any route matched by a `prerender` path
160+
- If you are using a `loader` on a pre-rendered route that has child routes, you will need to make sure the parent `loaderData` can be determined at run-time properly by either:
161+
- Pre-rendering all child routes so that the parent `loader` can be called at build-time for each child route path and rendered into a `.data` file, or
162+
- Use a `clientLoader` on the parent that can be called at run-time for non-pre-rendered child paths

integration/vite-prerender-test.ts

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -820,9 +820,9 @@ test.describe("Prerendering", () => {
820820
let result = build({ cwd });
821821
let stderr = result.stderr.toString("utf8");
822822
expect(stderr).toMatch(
823-
"Prerender: 2 invalid route export(s) in `routes/a` when prerendering " +
824-
"with `ssr:false`: headers, action. " +
825-
"See https://reactrouter.com/how-to/pre-rendering for more information."
823+
"Prerender: 2 invalid route export(s) in `routes/a` when pre-rendering " +
824+
"with `ssr:false`: `headers`, `action`. " +
825+
"See https://reactrouter.com/how-to/pre-rendering#invalid-exports for more information."
826826
);
827827
});
828828

@@ -848,10 +848,9 @@ test.describe("Prerendering", () => {
848848
let result = build({ cwd });
849849
let stderr = result.stderr.toString("utf8");
850850
expect(stderr).toMatch(
851-
"Prerender: 1 invalid route export in `routes/b` when using `ssr:false` " +
852-
"with `prerender` because the route is never prerendered so the loader " +
853-
"will never be called. See https://reactrouter.com/how-to/pre-rendering " +
854-
"for more information."
851+
"Prerender: 1 invalid route export in `routes/b` when pre-rendering " +
852+
"with `ssr:false`: `loader`. " +
853+
"See https://reactrouter.com/how-to/pre-rendering#invalid-exports for more information."
855854
);
856855
});
857856

@@ -875,12 +874,9 @@ test.describe("Prerendering", () => {
875874
let result = build({ cwd });
876875
let stderr = result.stderr.toString("utf8");
877876
expect(stderr).toMatch(
878-
"Prerender: 1 invalid route export in `routes/a` when using `ssr:false` " +
879-
"with `prerender`: `loader`. This is because the route has non-pre-rendered " +
880-
"children paths and does not have it's own `clientLoader` to be used " +
881-
"when those paths are hydrated as a SPA. You can fix this error by adding " +
882-
"a `clientLoader` to the route or by pre-rendering the children paths. " +
883-
"See https://reactrouter.com/how-to/pre-rendering for more information."
877+
"Prerender: 1 invalid route export in `routes/a` when pre-rendering " +
878+
"with `ssr:false`: `loader`. " +
879+
"See https://reactrouter.com/how-to/pre-rendering#invalid-exports for more information."
884880
);
885881
});
886882

packages/react-router-dev/vite/plugin.ts

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2516,7 +2516,7 @@ async function prerenderResourceRoute(
25162516
throw new Error(
25172517
`Prerender (resource): Received a ${response.status} status code from ` +
25182518
`\`entry.server.tsx\` while prerendering the \`${normalizedPath}\` ` +
2519-
`path.\n${content.toString('utf8')}`
2519+
`path.\n${content.toString("utf8")}`
25202520
);
25212521
}
25222522

@@ -2662,35 +2662,30 @@ async function validateSsrFalsePrerenderExports(
26622662
if (exports.includes("action")) invalidApis.push("action");
26632663
if (invalidApis.length > 0) {
26642664
errors.push(
2665-
`Prerender: ${invalidApis.length} invalid route export(s) in ` +
2666-
`\`${route.id}\` when prerendering with \`ssr:false\`: ` +
2667-
`${invalidApis.join(", ")}. ` +
2668-
"See https://reactrouter.com/how-to/pre-rendering for more information."
2665+
`Prerender: ${invalidApis.length} invalid route export(s) in \`${route.id}\` ` +
2666+
"when pre-rendering with `ssr:false`: " +
2667+
`${invalidApis.map((a) => `\`${a}\``).join(", ")}. ` +
2668+
"See https://reactrouter.com/how-to/pre-rendering#invalid-exports for more information."
26692669
);
26702670
}
26712671

26722672
// `loader` is only valid if the route is matched by a `prerender` path
26732673
if (!prerenderedRoutes.has(routeId)) {
26742674
if (exports.includes("loader")) {
26752675
errors.push(
2676-
`Prerender: 1 invalid route export in \`${route.id}\` when ` +
2677-
"using `ssr:false` with `prerender` because the route is never " +
2678-
"prerendered so the loader will never be called. " +
2679-
"See https://reactrouter.com/how-to/pre-rendering for more information."
2676+
`Prerender: 1 invalid route export in \`${route.id}\` ` +
2677+
"when pre-rendering with `ssr:false`: `loader`. " +
2678+
"See https://reactrouter.com/how-to/pre-rendering#invalid-exports for more information."
26802679
);
26812680
}
26822681

26832682
let parentRoute = route.parentId ? manifest.routes[route.parentId] : null;
26842683
while (parentRoute && parentRoute.id !== "root") {
26852684
if (parentRoute.hasLoader && !parentRoute.hasClientLoader) {
26862685
errors.push(
2687-
`Prerender: 1 invalid route export in \`${parentRoute.id}\` when using ` +
2688-
"`ssr:false` with `prerender`: `loader`. This is because the route " +
2689-
"has non-pre-rendered children paths and does not have it's own " +
2690-
"`clientLoader` to be used when those paths are hydrated as a SPA. " +
2691-
"You can fix this error by adding a `clientLoader` to the route or " +
2692-
"by pre-rendering the children paths. " +
2693-
"See https://reactrouter.com/how-to/pre-rendering for more information."
2686+
`Prerender: 1 invalid route export in \`${parentRoute.id}\` when ` +
2687+
"pre-rendering with `ssr:false`: `loader`. " +
2688+
"See https://reactrouter.com/how-to/pre-rendering#invalid-exports for more information."
26942689
);
26952690
}
26962691
parentRoute =

0 commit comments

Comments
 (0)