寻求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的构建产物:
- 先构建Next项目:
cd frontend && npm run build - 修改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
- 启动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
相关产品推荐
相关产品推荐

