如何在Next.js中实现带location.hash的URL服务端重定向?
解决Next.js中带Hash的旧书签重定向问题
因为浏览器不会把URL中的hash部分发送到服务器,所以服务端无法直接获取这部分内容处理重定向。针对你的场景,推荐以下几种实现平滑跳转的方案:
方案一:404页面即时客户端跳转(最简单)
用户访问已删除的/get-started/#setup会触发404,但可以在自定义404页面中加入一段优先执行的原生JS脚本,在页面内容渲染前完成跳转,用户几乎感知不到404页面。
代码示例(Pages Router)
// pages/404.js export default function Custom404() { return ( <> {/* 优先执行的跳转脚本 */} <script dangerouslySetInnerHTML={{ __html: ` const { pathname, hash } = window.location; if (pathname === '/get-started' && hash === '#setup') { window.location.replace('/setup'); } ` }} /> {/* 常规404内容(用户几乎看不到) */} <div>页面未找到</div> </> ); }
代码示例(App Router,Next.js 13+)
// app/404/page.js export default function NotFound() { return ( <> <script dangerouslySetInnerHTML={{ __html: ` const { pathname, hash } = window.location; if (pathname === '/get-started' && hash === '#setup') { window.location.replace('/setup'); } ` }} /> <div>页面未找到</div> </> ); }
方案二:客户端转参数+服务端中间件重定向
如果需要服务端完成重定向,可以先让客户端把hash转成查询参数,再触发服务端的重定向逻辑。
步骤1:全局注入客户端转换脚本
在自定义_document.js(Pages Router)中加入脚本,将hash转为查询参数:
// pages/_document.js import Document, { Html, Head, Main, NextScript } from 'next/document'; class MyDocument extends Document { render() { return ( <Html> <Head> <script dangerouslySetInnerHTML={{ __html: ` const path = window.location.pathname; const hash = window.location.hash.slice(1); // 去除#号 if (path === '/get-started' && hash === 'setup') { window.location.replace('/get-started?redirect=' + hash); } ` }} /> </Head> <body> <Main /> <NextScript /> </body> </Html> ); } } export default MyDocument;
步骤2:中间件处理服务端重定向
在项目根目录创建middleware.js,检测查询参数并完成重定向:
// middleware.js import { NextResponse } from 'next/server'; export function middleware(request) { const { pathname, searchParams } = request.nextUrl; if (pathname === '/get-started' && searchParams.get('redirect') === 'setup') { return NextResponse.redirect(new URL('/setup', request.url)); } return NextResponse.next(); }
方案说明
- 方案一无需额外服务端配置,实现成本最低,跳转速度快,适合大多数场景。
- 方案二适合需要服务端统一处理重定向逻辑、或有日志统计需求的场景。
内容的提问来源于stack exchange,提问作者PubSub
相关产品推荐
相关产品推荐

