2026-11-7 17:19
59
Next.js App Router:路由跳转 + 路由守卫
环境:
- App Router(你当前项目)Next14/15,区分客户端组件和服务端组件,路由守卫分3种方案。
路由跳转
1)客户端组件( "use client" )
使用 next/navigation 的 useRouter
JavaScript
"use client"; import { useRouter } from "next/navigation"; export default function Demo() { const router = useRouter(); return ( <> {/* 跳转 */} <button onClick={() => router.push("/chat")}>去聊天页</button> {/* 替换历史,回退不会回到本页 */} <button onClick={() => router.replace("/login")}>登录后跳转</button> {/* 返回上一页 */} <button onClick={() => router.back()}>返回</button> </> ); }
- router.push(path) :新增历史记录,可以回退
- router.replace(path) :替换当前历史,适合登录跳转 router.back() :回退
2)服务端组件 / 不需要JS:标签跳转
JavaScript
import Link from "next/link"; // 服务端组件,不需要 use client
JavaScript
<Link href=“/chat">前往聊天页面</Link>
3)后端API内跳转(route.ts)
JavaScript
// route.ts return Response.redirect(new URL("/login", req.url), 302);
路由守卫(权限校验)
App Router 没有像Vue‑router那样的全局beforeEach钩子,3种实现方案,按推荐排序:
方案1:middleware.ts【全局守卫,最优】⭐
在请求到达页面/接口之前执行,Edge运行,不渲染页面,适合登录鉴权。
放在项目根目录,不是src下面: /middleware.ts
✅优点:
- 请求阶段拦截,页面还没渲染,性能最好;
- 同时保护页面page,也保护api接口;
- Edge运行。
限制:
- middleware拿不到supabase service‑role密钥!
- 只能读取cookie/header,不能访问数据库。
- 复杂数据库鉴权不能写在这里。
方案2:layout.tsx 局部守卫(页面组权限)
如果一组页面需要鉴权,在对应文件夹写layout.tsx
客户端layout(use‑client)
JavaScript
// src/app/chat/layout.tsx "use client"; import { useRouter } from "next/navigation"; import { useEffect } from "react"; export default function ChatLayout({children}:{children:React.ReactNode}){ const router = useRouter(); useEffect(()=>{ // 检查登录状态 const isLogin = false; if(!isLogin){ router.replace("/login"); } },[router]); return <>{children}</>; }
服务端layout(推荐,不会闪烁)
工程最佳实践组合(适合AI Agent项目)
- middleware.ts :做基础登录拦截,拦截大部分访问;
- 服务端layout:受保护页面二次校验;
- 每个route.ts API接口:再做一次权限校验(防御,不能只靠中间件)。
常见坑点
- redirect() 来自 next/navigation ,服务端组件使用;不要用useRouter。
- middleware.ts不能读取 .env 私有密钥,不能访问数据库。
- 客户端守卫会出现页面闪一下,优先服务端layout/middleware。
- middleware文件名固定:middleware.ts,放在项目根目录,不是src下。
- 接口一定要单独鉴权!middleware可以绕过,不能只依赖middleware做接口安全。 :::