Next.js对接Firestore集合实现服务端渲染动态路由的问题求助
问题排查与实现方案
现有代码核心问题
- 动态路由参数名不匹配:
- 你的API路由文件名为
pages/api/[doc].js,框架会自动将路径参数挂载到req.query.doc,你代码中写的req.query.name无法拿到正确的文档ID - 你的页面文件名为
pages/[shoal].jsx,路由参数会挂载到router.query.shoal,你代码中取router.query.name会得到undefined,导致请求路径错误
- 你的API路由文件名为
- 现有实现为客户端渲染(CSR),不符合你要求的服务端渲染(SSR)需求:用SWR拉取数据的逻辑在客户端执行,首屏会出现Loading状态,无法被搜索引擎直接爬取内容
正确SSR实现方案(无需额外API路由)
直接在页面的getServerSideProps中查询Firestore,服务端直出渲染结果,性能更高且符合SSR要求:
第一步:修改页面文件命名
将页面文件改名为pages/[doc].jsx,匹配你要的test.com/[文档ID]访问路径
第二步:编写页面代码
// 请先确保你已经正确初始化了服务端可用的Firestore db实例 import db from '你的Firestore初始化文件路径' function Doc({ docData }) { return ( <div> <p>Title: {docData.title}</p> </div> ) } export async function getServerSideProps(context) { // 路由参数和文件名保持一致,所以取context.params.doc const docId = context.params.doc const docSnapshot = await db.collection("docs").doc(docId).get() // 文档不存在返回404 if (!docSnapshot.exists) { return { notFound: true } } return { props: { docData: docSnapshot.data() } } } export default Doc
如果你坚持使用原有SWR方案的修复方法
- 修改
pages/api/[doc].js代码:export default (req, res) => { db.collection("docs") // 把req.query.name改成req.query.doc .doc(req.query.doc) .get() .then((doc) => { if (!doc.exists) return res.status(404).json({ error: '文档不存在' }) res.json(doc.data()); }) .catch((error) => { res.status(500).json({ error }); }); }; - 修改
pages/[shoal].jsx代码:import { useRouter } from "next/router"; import useSWR from "swr"; const fetcher = async (...args) => { const res = await fetch(...args); if (!res.ok) throw new Error('请求失败') return res.json(); }; function Doc() { const router = useRouter(); // 把name改成shoal,和文件名保持一致 const { shoal } = router.query; const { data, error } = useSWR(shoal ? `/api/${shoal}` : null, fetcher); if (error) return "文档加载失败"; if (!data) return "Loading..."; return ( <div> <p>Title: {data.title}</p> </div> ); } export default Doc;
内容的提问来源于stack exchange,提问作者jl98
相关产品推荐
相关产品推荐

