Router.push()跳转后Node.js fs.readdirSync未触发服务端代码的解决方法
解决方案:触发根页面服务端代码执行的跳转方式
你遇到的核心问题是 Next.js的Router.push()属于客户端SPA跳转,不会向服务器发起新请求,所以根页面里依赖服务端环境的fs.readdirSync()代码完全不会运行——毕竟SPA跳转只是在浏览器端切换页面内容,根本没给服务器触发代码的机会。
下面给你两种针对性的解决方案,按需选择:
方案1:直接触发完整浏览器跳转(最简单直接)
用原生的window.location.href替代Router.push(),这种方式会让浏览器像手动输入网址一样发起完整的GET请求,服务器必然会处理根路径的请求,你的服务端文件读取代码也就会执行了。
修改你的跳转逻辑:
goTo = (item) => { console.log('goTo: ', item); window.location.href = '/'; }
唯一的小缺点是会有页面刷新的白屏,但胜在逻辑简单,完全满足你“必须执行服务端代码”的核心需求。
方案2:保留SPA体验+服务端数据获取(进阶优化)
如果想兼顾SPA跳转的流畅性,同时获取服务端的最新文件列表,可以结合Next.js的服务端数据获取能力和API路由来实现:
步骤1:将服务端逻辑迁移到getServerSideProps
在根页面pages/wiki/index.js中,把读取文件列表的逻辑放到getServerSideProps里——这是Next.js专门用于服务端数据获取的方法,会在每次请求(包括客户端跳转后的首次渲染)时执行:
export async function getServerSideProps(context) { const { query } = context; const versions = articles.getVersions(`articles/${query.article}/`); return { props: { versions } // 把数据传递给页面组件 } } function WikiPage({ versions }) { // 用获取到的versions渲染页面内容 return ( <div> {/* 你的文件列表渲染逻辑 */} </div> ) } export default WikiPage;
步骤2:创建API路由用于客户端补取数据
如果客户端跳转后发现数据缺失(比如某些极端情况),可以通过API路由从服务端重新获取:
创建pages/api/get-versions.js:
import articles from '../../path/to/Articles'; // 替换成你的Articles模块路径 export default function handler(req, res) { const { article } = req.query; try { const versions = articles.getVersions(`articles/${article}/`); res.status(200).json({ versions }); } catch (err) { res.status(500).json({ error: 'Failed to fetch versions' }); } }
步骤3:在页面组件中处理数据补取
在根页面组件中,用useEffect检查数据是否存在,如果不存在就调用API获取:
import { useEffect, useState } from 'react'; import { useRouter } from 'next/router'; function WikiPage({ versions: initialVersions }) { const [versions, setVersions] = useState(initialVersions); const { article } = useRouter().query; // 用useRouter获取query参数 useEffect(() => { // 如果初始数据为空,从API拉取 if (!versions && article) { fetch(`/api/get-versions?article=${encodeURIComponent(article)}`) .then(res => res.json()) .then(data => setVersions(data.versions)); } }, [versions, article]); // 渲染逻辑 return ( <div> {versions ? ( /* 渲染文件列表 */ ) : ( <p>加载中...</p> )} </div> ) } export default WikiPage;
这种方式既保留了SPA跳转的流畅性,又能确保你获取到服务端的最新文件列表。
内容的提问来源于stack exchange,提问作者Vinícius de Araújo Portela
相关产品推荐
相关产品推荐

