Replies: 2 comments 1 reply
-
This is document To fix the problem, I am having to use hard code in the middleware |
Beta Was this translation helpful? Give feedback.
-
Hi, I would just like to make a couple of precisions. As you point out this because streaming kick in, if I have this root page, without a import { setTimeout } from "node:timers/promises";
import { redirect } from 'next/navigation'
export const dynamic = 'force-dynamic'
export default async function Home() {
await setTimeout(450)
redirect("/home")
} Then when I navigate with a browser, or even cURL my server, I get a 307. ![]() ❯ curl localhost:1234 -v
* Host localhost:1234 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
* Trying [::1]:1234...
* Connected to localhost (::1) port 1234
> GET / HTTP/1.1
> Host: localhost:1234
> User-Agent: curl/8.7.1
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 307 Temporary Redirect
< Vary: RSC, Next-Router-State-Tree, Next-Router-Prefetch, Accept-Encoding
< Location: /home
< X-Powered-By: Next.js
< Cache-Control: private, no-cache, no-store, max-age=0, must-revalidate
< Content-Type: text/html; charset=utf-8
< Date: Tue, 03 Jun 2025 07:42:59 GMT
< Connection: keep-alive
< Keep-Alive: timeout=5
< Transfer-Encoding: chunked However, when a suspense boundary is somehow present, for example through a root loading file, streaming kicks in, and now even the same cURL command does: * Request completely sent off
< HTTP/1.1 200 OK
< Vary: RSC, Next-Router-State-Tree, Next-Router-Prefetch, Accept-Encoding
< X-Powered-By: Next.js
< Cache-Control: private, no-cache, no-store, max-age=0, must-revalidate
< Content-Type: text/html; charset=utf-8
< Date: Tue, 03 Jun 2025 07:49:09 GMT
< Connection: keep-alive
< Keep-Alive: timeout=5
< Transfer-Encoding: chunked I know this is not ideal, but what's happened here, is that streaming began, eagerly, and for that, headers are sent first, including the status of the request. Later on while rendering, a redirect is found, and now we need to "out of order" redirect to a new location. For that: <meta
id="__next-page-redirect"
http-equiv="refresh"
content="1;url=/home"
/> These sections in Google's Search Console docs:
Hint that, it is OK, perhaps, not the most optimal/ideal, but ok anyway. I know that for a bot, or my cURL request, is not good enough, because at the end of the day, it didn't follow to the content If a path can be potentially redirected, and it is important for bots/crawlers, from your point of view, try to keep the path to the redirect call, out of Suspense. I know, again, not ideal, not always possible, and prone to regressions, but it is a way out. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Summary
In my Next.js 14 project using the App Router, I expected server-side redirects to happen cleanly—without rendering any content and with a proper redirect status (like 307 or 308).
However, what actually happens is:
The original request returns status 200.
The redirected request also returns 200.
Some content is still sent to the client before the redirect occurs.
This breaks the assumption of a clean, server-handled redirect and can cause flickering or unintended content exposure. I believe redirects should happen with no content streaming and with proper HTTP redirect status codes.
This is my implementation:
Additional information
Example
No response
Beta Was this translation helpful? Give feedback.
All reactions