Next.js静态生成页面结合Middleware的请求头访问问题
解决方案
你用的是Next.js 13的pages目录,且页面由getStaticProps生成静态页——这类页面的服务端渲染逻辑在构建阶段就已完成,无法在静态页的服务端代码中获取用户请求时的动态信息(比如请求头)。结合你的场景,以下是几个可行的解决办法:
方法一:直接用浏览器原生API获取referrer
浏览器自带document.referrer属性,可直接获取当前页面的来源地址,无需依赖服务端传递。在标记了"use client"的组件里直接使用即可:
// 客户端组件内 useEffect(() => { const referrer = document.referrer; // 根据referrer判断是否为外部域名,执行对应渲染逻辑 if (referrer && !referrer.includes('你的域名')) { // 渲染外部跳转对应的内容 } }, []);
这个方法最简洁,不需要修改现有middleware,直接在客户端完成判断。
方法二:通过Middleware将referrer存入Cookie,客户端读取
如果需要保证referrer的准确性(避免客户端篡改),可以修改middleware把referrer存入Cookie,再由客户端读取:
修改middleware.ts
import { NextResponse } from 'next/server' import type { NextRequest } from 'next/server' export function middleware(request: NextRequest) { const referer = request.headers.get('referer'); const response = NextResponse.next(); // 将referrer存入会话级Cookie if (referer) { response.cookies.set('page_referrer', referer, { path: '/', httpOnly: false, // 设置为false允许客户端读取 secure: process.env.NODE_ENV === 'production', }); } return response; } export const config = { matcher: '/events/:path*', }
客户端组件读取Cookie
// 客户端组件内 useEffect(() => { const getCookie = (name: string) => { const value = `; ${document.cookie}`; const parts = value.split(`; ${name}=`); if (parts.length === 2) return parts.pop()?.split(';').shift(); }; const referrer = getCookie('page_referrer'); // 后续判断逻辑同方法一 }, []);
方法三:通过API路由中转获取referrer
如果需要从服务端层面验证referrer,可以创建一个API路由,客户端通过请求该接口获取信息:
创建pages/api/get-referrer.ts
import type { NextApiRequest, NextApiResponse } from 'next'; export default function handler(req: NextApiRequest, res: NextApiResponse) { const referrer = req.headers.referer; res.status(200).json({ referrer }); }
客户端组件请求接口
// 客户端组件内 useEffect(() => { const fetchReferrer = async () => { const response = await fetch('/api/get-referrer'); const data = await response.json(); const referrer = data.referrer; // 处理渲染逻辑 }; fetchReferrer(); }, []);
需要注意:getStaticProps是构建阶段执行的,完全无法获取用户请求时的动态数据,所有需要根据用户请求动态判断的逻辑,都必须放在客户端或请求阶段运行的服务端代码(比如API路由、Middleware)中。
内容的提问来源于stack exchange,提问作者strangecarr
相关产品推荐
相关产品推荐

