Next.js使用Express自定义服务器时getInitialProps重复调用问题
问题原因
- 路由注册顺序错误:Express 服务的
server.listen()启动逻辑写在了通配符路由server.get('*')之前,服务启动时路由尚未完成挂载,请求会先触发 Next.js 内置路由处理,再触发自定义路由逻辑,产生额外调用。 - 未正确关闭 Next.js 内置文件路由:你提到已禁用 pages 文件夹路由,但初始化 Next 实例时未添加
useFileSystemPublicRoutes: false配置,Next.js 默认仍会扫描 pages 目录匹配路由,和自定义路由产生冲突,导致重复执行getInitialProps。 - React.StrictMode 开发环境特性:开启 StrictMode 时,开发环境下 React 会重复调用部分生命周期方法(包括客户端侧的
getInitialProps)用于检测副作用,你观察到的两次调用分别是服务端渲染触发、StrictMode 下客户端重复执行的结果;关闭 StrictMode 后因为前述两个路由冲突问题,多触发了一次路由匹配调用,因此变成三次。
解决方案
- 修正路由注册顺序,将通配符路由逻辑移到
server.listen()之前,确保服务启动前所有路由已完成挂载。 - 初始化 Next.js 实例时添加
useFileSystemPublicRoutes: false配置,彻底关闭内置文件系统路由,避免路由冲突。 - 开发环境下的 StrictMode 重复调用属于官方预设调试行为,生产环境构建后会自动消失,无需额外处理。
修正后的 server.js 参考代码
require('dotenv').config(); const express = require('express'); const next = require('next'); const mongoose = require('mongoose'); const dev = process.env.NODE_ENV !== 'production'; // 新增配置关闭内置文件路由 const app = next({ dev, useFileSystemPublicRoutes: false }); mongoose.connect(process.env.DB_URI) .then(()=>{ console.log('>Succesfully connected to the database'); app.prepare() .then(() => { const server = express(); // 先注册路由 server.get('*', (req, res)=>{ app.render(req, res, '/index', {something:true}); }) // 最后启动服务 server.listen(3000, (req, res) =>{ console.log('>Listening on port 3000'); }); }) .catch((ex) => { console.error(ex.stack); process.exit(1); }) }) .catch(e=>{ console.log('<!>Error connecting to database: \n' + e); });
内容的提问来源于stack exchange,提问作者Dragnea Andrei
相关产品推荐
相关产品推荐

