如何配置Sanity实时预览?解决req.query为空导致resolveHref返回undefined问题
解决Sanity Next.js个人网站模板预览时req.query为空导致路由无法解析的问题
问题分析
使用Sanity提供的Next.js个人网站模板时,预览功能依赖req.query获取documentType和slug参数,但该对象为空,导致resolveHref返回undefined,无法完成预览跳转。
解决方案
1. 确认Sanity Studio预览参数传递正确
检查Sanity各文档类型的schema配置,确保预览URL携带了documentType、slug和secret参数:
// sanity/schemas/post.js 示例 export default { name: 'post', type: 'document', preview: { select: { title: 'title', slug: 'slug.current', }, prepare(selection) { return { title: selection.title, subtitle: selection.slug, url: `/api/preview?documentType=post&slug=${selection.slug}&secret=${process.env.SANITY_PREVIEW_SECRET}` } } }, // ... 其他schema配置 }
如果是首页这类无slug的文档,要传递特殊标识(比如slug=home),确保resolveHref能识别。
2. 适配Next.js路由模式的参数获取方式
- Pages Router(原pages/api/preview.js):确认请求是GET方法,
req.query仅在GET请求中生效。如果是POST请求,需改用req.body获取参数。 - App Router(app/api/preview/route.js):Next.js 13+的App Router中,API路由需通过
request.nextUrl.searchParams获取URL参数,替换原有的req.query:
import { NextResponse } from 'next/server' import { createClient } from '@sanity/client' import getSecret from '@/lib/getSecret' import resolveHref from '@/lib/resolveHref' const _client = createClient({ projectId: process.env.NEXT_PUBLIC_SANITY_PROJECT_ID, dataset: process.env.NEXT_PUBLIC_SANITY_DATASET, apiVersion: '2024-01-01', useCdn: false }) export async function GET(request) { const searchParams = request.nextUrl.searchParams const secret = searchParams.get('secret') const documentType = searchParams.get('documentType') const slug = searchParams.get('slug') const previewData = {} if (process.env.SANITY_REQUIRE_PREVIEW_SECRET === 'true' && !secret) { return new NextResponse('Invalid secret', { status: 401 }) } if (secret) { const token = process.env.SANITY_API_READ_TOKEN if (!token) { throw new Error('SANITY_API_READ_TOKEN环境变量未配置') } const client = _client.withConfig({ token }) const storedSecret = await getSecret(client, 'preview.secret') if (secret !== storedSecret) { return new NextResponse('Invalid secret', { status: 401 }) } previewData.token = token } const href = resolveHref(documentType, slug) if (!href) { return new NextResponse('无法根据文档类型和slug解析预览URL', { status: 400 }) } const response = NextResponse.redirect(new URL(href, request.url)) response.cookies.set('__prerender_bypass', '1', { path: '/' }) if (previewData.token) { response.cookies.set('sanity-preview-token', previewData.token, { path: '/' }) } return response }
3. 调试参数为空问题
在API路由中添加日志,确认请求参数是否正常传递:
// Pages Router示例 export default async function preview(req, res) { console.log('请求URL:', req.url) console.log('Query参数:', req.query) // ... 原有逻辑 }
如果日志中无参数,检查:
- 请求是否为GET方法(POST请求参数在
req.body) - Sanity Studio的预览URL是否拼写正确
- 反向代理或CDN是否过滤了请求参数
4. 完善resolveHref函数逻辑
确保resolveHref能处理空slug或特殊文档类型的情况:
export function resolveHref(documentType, slug) { switch (documentType) { case 'post': return slug ? `/posts/${slug}` : null case 'page': return slug === 'home' ? '/' : `/${slug}` case 'project': return `/projects/${slug}` default: // 未匹配到类型时返回默认预览页或首页 return '/' } }
内容的提问来源于stack exchange,提问作者Burger Sasha
相关产品推荐
相关产品推荐

