Next.js项目双布局实现:路由分组与会话驱动布局切换
实现Next.js双布局与会话路由判断
1. 创建落地页布局组件
先新建MainLayout组件,包含落地页所需的导航栏、Hero区域、页脚等元素:
// src/components/Layout/MainLayout.tsx import React from 'react'; import LandingNavbar from '../Navbar/LandingNavbar'; import LandingHero from '../Hero/LandingHero'; import LandingFooter from '../Footer/LandingFooter'; const MainLayout = ({ children }: { children: React.ReactNode }) => { return ( <div className="landing-container"> <LandingNavbar /> <LandingHero /> <main className="landing-content">{children}</main> <LandingFooter /> </div> ); }; export default MainLayout;
2. 修改根布局逻辑
更新RootLayout,加入会话判断、路由重定向逻辑,并切换渲染对应布局:
import type { Metadata } from "next"; import { Inter, Poppins } from "next/font/google"; import { redirect } from "next/navigation"; import "../globals.css"; import ThemeProvider from "src/provider/ThemeProvider/ThemeProvider"; import GlobalProvider from "src/provider/GlobalProvider/GlobalProvider"; import UserLayout from "src/components/Layout/UserLayout"; import MainLayout from "src/components/Layout/MainLayout"; // 引入落地页布局 const inter = Inter({ subsets: ['latin'], weight: ['400', '500', '600', '700', '900'], style: ['normal'], variable: '--font-inter' }); const poppins = Poppins({ subsets: ['latin'], weight: ['400', '500', '600', '700', '900'], style: ['italic', 'normal'], variable: '--font-poppins' }) // 动态设置落地页元数据 export async function generateMetadata(): Promise<Metadata> { return { title: "ValuBox - 便捷缴费与流量充值平台", description: "一站式解决水电费、数据流量与话费购买需求。", }; } export default async function RootLayout({ children, }: Readonly<{ children: React.ReactNode; }>) { // 替换为你实际的会话获取逻辑(比如从cookies、auth库读取并验证) const session = await getValidUserSession(); const isSessionValid = session && session.expires > new Date().toISOString(); // 会话有效则重定向到用户面板 if (isSessionValid) { redirect("/user/dashboard"); } return ( <html lang="en"> <body className={`${inter.className} ${poppins.className}`}> <GlobalProvider> <ThemeProvider> <MainLayout> {children} </MainLayout> </ThemeProvider> </GlobalProvider> </body> </html> ); }
3. 独立配置用户路由布局
在app/user目录下新建专属布局,确保用户面板路由统一使用UserLayout:
// app/user/layout.tsx import UserLayout from "src/components/Layout/UserLayout"; import ThemeProvider from "src/provider/ThemeProvider/ThemeProvider"; import GlobalProvider from "src/provider/GlobalProvider/GlobalProvider"; // 设置用户面板元数据 export const metadata: Metadata = { title: "ValuBox - 用户控制台", description: "管理账户、查看交易记录、充值钱包与转账。", }; export default function UserRootLayout({ children, }: { children: React.ReactNode; }) { return ( <GlobalProvider> <ThemeProvider> <UserLayout> {children} </UserLayout> </ThemeProvider> </GlobalProvider> ); }
4. 路由保护(可选但推荐)
新建中间件保护/user/*路由,防止未认证用户直接访问:
// middleware.ts import { NextResponse } from 'next/server'; import type { NextRequest } from 'next/server'; export async function middleware(request: NextRequest) { // 复用会话验证逻辑 const session = await getValidUserSession(request); const isAuthenticated = session && session.expires > new Date().toISOString(); if (request.nextUrl.pathname.startsWith('/user') && !isAuthenticated) { return NextResponse.redirect(new URL('/', request.url)); } return NextResponse.next(); } // 指定中间件生效的路由 export const config = { matcher: ['/user/:path*'], };
关键说明
- 替换代码中的
getValidUserSession为你项目实际的会话验证方法(比如next-auth的getServerSession,或自定义的cookie验证逻辑)。 - 落地页的Hero区域如果仅需在首页显示,可通过路由判断或让首页单独渲染,避免所有落地页重复展示。
内容的提问来源于stack exchange,提问作者Chibuike Ilo
相关产品推荐
相关产品推荐

