如何配置服务端文件使Heroku托管的NextJS应用读取正确目录?
问题核心
你当前的配置是照搬了纯客户端React(CRA)的静态托管逻辑,不符合Next.js的运行规则:Next.js 默认执行npm run build后生成的构建产物存放在.next目录,且内置了服务端处理逻辑,不能直接通过express.static托管静态文件+返回index.html的方式运行。
以下提供两种适配方案,根据你的项目需求选择即可:
方案一:Express集成Next.js(推荐,可保留Next.js全量特性)
这种方案可以让你的Express服务同时承载后端API和Next.js前端服务,支持SSR、ISR、API路由等所有Next.js特性。
- 调整server.js代码
首先在文件顶部引入并初始化Next.js实例:
const next = require('next') // 判断是否为开发环境 const dev = process.env.NODE_ENV !== 'production' // 指定Next.js项目的存放目录 const nextApp = next({ dev, dir: './client-next-app' }) const nextHandler = nextApp.getRequestHandler()
替换你原来写的Next.js判断分支代码,删掉静态托管相关逻辑:
} else if ( process.env.NODE_ENV === 'production' && process.env.NODE_TECHNOLOGY === `next` ) { // 等待Next.js实例初始化完成 nextApp.prepare().then(() => { // 所有非API请求交由Next.js处理 app.get('*', (req, res) => { return nextHandler(req, res) }) }) }
- 调整根目录package.json配置
在启动脚本中新增NODE_TECHNOLOGY=next环境变量,确保Next.js分支可以被命中:
"scripts": { // 其余脚本保持不变,仅修改start命令 "start": "NODE_ENV=production NODE_TECHNOLOGY=next node server.js", "heroku-postbuild": "NPM_CONFIG_PRODUCTION=false npm install --prefix client-next-app && npm run build --prefix client-next-app" }
⚠️ 注意:所有Express的API路由必须写在上述Next.js通配路由之前,否则API请求会被Next.js拦截处理。
方案二:导出纯静态文件部署(仅适用无服务端特性的Next项目)
如果你的项目仅用到Next.js的静态页面生成能力,没有使用SSR、ISR、服务端API路由等特性,可以选择导出纯静态文件,沿用你原来的静态托管逻辑。
- 调整Next项目package.json配置
新增export命令:
"scripts": { "dev": "next dev", "build": "next build", "export": "next export", "start": "next start -p $PORT" }
- 调整根目录package.json的构建脚本
在heroku-postbuild中新增导出命令:
"heroku-postbuild": "NPM_CONFIG_PRODUCTION=false npm install --prefix client-next-app && npm run build --prefix client-next-app && npm run export --prefix client-next-app"
- 调整server.js的Next分支路径
next export会生成纯静态产物存放在out目录,替换路径即可:
} else if ( process.env.NODE_ENV === 'production' && process.env.NODE_TECHNOLOGY === `next` ) { app.use(express.static(path.join(path.resolve(), 'client-next-app/out'))) app.get('*', (req, res) => res.sendFile( path.resolve(path.resolve(), 'client-next-app', 'out', 'index.html') ) ) }
同样需要在启动脚本中加上NODE_TECHNOLOGY=next环境变量。
内容的提问来源于stack exchange,提问作者Kirasiris
相关产品推荐
相关产品推荐

