+ }
+ `,
+ },
+ });
+
+ appFixture = await createAppFixture(fixture);
+
+ // Document loads
+ let requests = captureRequests(page);
+ let app = new PlaywrightFixture(appFixture, page);
+ await app.goto("/redirect");
+ await page.waitForSelector("#target");
+ expect(requests).toEqual([]);
+
+ // Client side navigations
+ await app.goto("/", true);
+ app.clickLink("/redirect");
+ await page.waitForSelector("#target");
+ expect(requests).toEqual(["/redirect.data"]);
+ });
});
});
diff --git a/packages/react-router-dev/vite/plugin.ts b/packages/react-router-dev/vite/plugin.ts
index 96b51e1711..543e03ec7b 100644
--- a/packages/react-router-dev/vite/plugin.ts
+++ b/packages/react-router-dev/vite/plugin.ts
@@ -2761,7 +2761,8 @@ async function prerenderData(
let response = await handler(request);
let data = await response.text();
- if (response.status !== 200) {
+ // 202 is used for `.data` redirects
+ if (response.status !== 200 && response.status !== 202) {
throw new Error(
`Prerender (data): Received a ${response.status} status code from ` +
`\`entry.server.tsx\` while prerendering the \`${prerenderPath}\` ` +
@@ -2780,6 +2781,8 @@ async function prerenderData(
return data;
}
+let redirectStatusCodes = new Set([301, 302, 303, 307, 308]);
+
async function prerenderRoute(
handler: RequestHandler,
prerenderPath: string,
@@ -2796,7 +2799,29 @@ async function prerenderRoute(
let response = await handler(request);
let html = await response.text();
- if (response.status !== 200) {
+ if (redirectStatusCodes.has(response.status)) {
+ // This isn't ideal but gets the job done as a fallback if the user can't
+ // implement proper redirects via .htaccess or something else. This is the
+ // approach used by Astro as well so there's some precedent.
+ // https://github.com/withastro/roadmap/issues/466
+ // https://github.com/withastro/astro/blob/main/packages/astro/src/core/routing/3xx.ts
+ let location = response.headers.get("Location");
+ // A short delay causes Google to interpret the redirect as temporary.
+ // https://developers.google.com/search/docs/crawling-indexing/301-redirects#metarefresh
+ let delay = response.status === 302 ? 2 : 0;
+ html = `
+
+Redirecting to: ${location}
+
+
+
+
+
+ Redirecting from ${normalizedPath} to ${location}
+
+
+