You need to enable JavaScript to run this app. 如何配置服务端文件使Heroku托管的NextJS应用读取正确目录?
优惠活动
大模型
产品
解决方案
定价
更多

如何配置服务端文件使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特性。

  1. 调整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)
    })
  })
} 
  1. 调整根目录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路由等特性,可以选择导出纯静态文件,沿用你原来的静态托管逻辑。

  1. 调整Next项目package.json配置
    新增export命令:
"scripts": {
    "dev": "next dev",
    "build": "next build",
    "export": "next export",
    "start": "next start -p $PORT"
}
  1. 调整根目录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"
  1. 调整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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.20 16:36:09