You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

寻求Adonisjs与Nextjs集成实现方案及技术指导

AdonisJS + NextJS 集成实操方案

我之前做过几套AdonisJS和NextJS的全栈集成项目,虽然没有像Adonuxt那样的现成包,但自己搭一套适配逻辑其实并不复杂,分享下我的实操经验:

核心适配思路

核心是让AdonisJS作为统一的服务入口:

  • 后端API请求直接由Adonis处理(比如/api/*路由)
  • 前端页面/静态资源请求转发给NextJS处理(开发环境代理,生产环境直接serve构建产物)
  • 如果需要SSR,Adonis可以调用Next的渲染能力,把渲染后的HTML返回给客户端

分步实现方案

1. 项目初始化

先分别创建Adonis和Next项目,建议把Next放在Adonis根目录下,保持结构清晰:

# 创建AdonisJS项目(选web或api模式,根据需求)
npm init adonis-ts-app@latest adonis-next-app
cd adonis-next-app

# 在Adonis根目录下创建NextJS项目
npx create-next-app@latest frontend

2. 配置开发环境代理

开发阶段,我们需要让Adonis把前端请求转发给Next的开发服务器(默认端口3000)。这里提供两种常用方式:

方式1:自定义中间件转发请求

创建一个NextProxy中间件:

// app/Middleware/NextProxy.ts
import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import proxy from 'http-proxy'

const proxyServer = proxy.createProxyServer({})

export default class NextProxy {
  public async handle({ request, response }: HttpContextContract, next: () => Promise<void>) {
    // 排除API路由,交给Adonis处理
    if (request.url().startsWith('/api')) {
      await next()
      return
    }

    // 转发所有其他请求到Next开发服务器
    proxyServer.web(request.request, response.response, {
      target: 'http://localhost:3000',
      changeOrigin: true,
    })
  }
}

然后在start/kernel.ts里注册这个中间件到全局中间件组:

Server.middleware.register([
  () => import('@ioc:Adonis/Core/BodyParser'),
  () => import('App/Middleware/NextProxy'), // 添加这行
])

方式2:直接在Adonis控制器中调用Next的请求处理器

如果需要SSR场景,这种方式更灵活可控:

// app/Controllers/Http/NextController.ts
import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import next from 'next'
import path from 'path'

// 初始化Next应用
const dev = process.env.NODE_ENV !== 'production'
const nextApp = next({
  dev,
  dir: path.join(__dirname, '../../frontend'), // 指定Next项目目录
})
const nextHandler = nextApp.getRequestHandler()

export default class NextController {
  public async handle({ request, response }: HttpContextContract) {
    // 确保Next应用已准备好
    await nextApp.prepare()
    // 让Next处理请求
    await nextHandler(request.request, response.response)
    // 标记响应已完成,避免Adonis重复发送
    response.response.finished = true
  }
}

然后在start/routes.ts中配置路由:

// 所有非API路由交给Next处理
Route.get('*', 'NextController.handle')

// 你的API路由
Route.group(() => {
  Route.get('/users', 'UsersController.index')
  // ...其他API
}).prefix('/api')

3. 生产环境配置

生产环境不需要代理,直接让Adonis serve Next的构建产物:

  1. 先构建Next项目:cd frontend && npm run build
  2. 修改Adonis的静态资源配置,让它能访问Next的构建产物:
// config/static.ts
import { AssetsConfig } from '@ioc:Adonis/Core/Static'

const staticConfig: AssetsConfig = {
  enabled: true,
  dotFiles: 'ignore',
  etag: true,
  lastModified: true,
  // 添加Next的静态资源目录
  directories: [
    'public',
    '../frontend/out', // Next13+的构建目录是out,旧版本是.next/static
  ],
}

export default staticConfig
  1. 启动Adonis服务时,确保Next已经构建完成,直接运行node ace serve --production即可。

关键注意点

  • 环境变量共享:把Adonis的环境变量传递给Next,可以在frontend/next.config.js中配置:
module.exports = {
  env: {
    API_URL: process.env.API_URL || 'http://localhost:3333/api',
  },
}
  • 会话与认证:如果用Adonis的Auth系统,可以在Next页面中通过getServerSideProps调用Adonis的API获取用户信息,或者在Adonis控制器中把用户信息作为props传给Next页面。
  • 端口冲突:开发时Adonis默认端口3333,Next默认3000,要确保两者端口不冲突,或者修改其中一个的端口配置。
  • 响应处理:在调用Next的请求处理器后,一定要标记response.response.finished = true,否则Adonis会尝试再次发送响应,导致错误。

替代方案参考

如果你的项目更偏向前端主导,也可以让Next作为主服务,通过API请求调用Adonis的后端接口。但这种方式会失去Adonis作为全栈框架的一些优势(比如统一的中间件、数据库集成、认证逻辑),所以更推荐让Adonis作为统一入口的方案。

内容的提问来源于stack exchange,提问作者Manos Kalogeropoulos

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 06:39:11