Next.js无法用环境变量配置重写,如何实现环境依赖路由重写?
我用Next.js做前端、Express.js做后端开发应用,开发阶段直接跑各自的开发服务器就能正常工作,但生产环境打算用Docker部署,这时候API地址得改成容器名(不是localhost),而且开发和生产环境要用不同端口。
开发阶段我硬编码了路由重写配置,代码如下:
const nextConfig = { reactStrictMode: true, async rewrites() { return [ { source: "/api/:path*", destination: `http://localhost:5000/api/:path*`, }, { source: "/auth/:path*", destination: `http://localhost:5000/auth/:path*`, }, ]; }, }; module.exports = nextConfig;
这个配置在开发环境没问题,但切换到生产环境时,我想基于环境变量设置重写的目标URL——开发环境指向http://localhost:5000/api,生产环境指向http://api:5100/api(对应Docker容器)。
查了相关内容后,发现Next.js的next.config.js里没法直接用环境变量,想问问有没有其他办法实现这种依赖环境的路由重写?
方案1:使用自定义服务器(Custom Server)
用Express搭建自定义服务器替代Next.js默认服务器,在服务器层直接根据环境变量配置路由转发,完全绕过next.config.js的限制。
示例代码:
// server.js const express = require('express'); const next = require('next'); const { createProxyMiddleware } = require('http-proxy-middleware'); const dev = process.env.NODE_ENV !== 'production'; const app = next({ dev }); const handle = app.getRequestHandler(); // 从环境变量读取后端地址 const API_BASE_URL = process.env.API_BASE_URL || 'http://localhost:5000'; app.prepare().then(() => { const server = express(); // 配置代理转发 server.use('/api', createProxyMiddleware({ target: API_BASE_URL, changeOrigin: true, })); server.use('/auth', createProxyMiddleware({ target: API_BASE_URL, changeOrigin: true, })); // 处理Next.js页面路由 server.all('*', (req, res) => { return handle(req, res); }); server.listen(process.env.PORT || 3000, (err) => { if (err) throw err; console.log('Server ready'); }); });
修改package.json启动脚本:
{ "scripts": { "dev": "NODE_ENV=development API_BASE_URL=http://localhost:5000 node server.js", "build": "next build", "start": "NODE_ENV=production API_BASE_URL=http://api:5100 node server.js" } }
Docker部署时,直接在容器环境变量中设置API_BASE_URL=http://api:5100即可。
方案2:用API路由作为转发中间层
在Next.js的pages/api目录下创建转发文件,把前端的API请求先转到Next.js的API路由,再由该路由转发到后端服务,这样就能在API路由文件里正常使用环境变量。
示例:创建pages/api/[...path].js
import { createProxyMiddleware } from 'http-proxy-middleware'; const API_BASE_URL = process.env.API_BASE_URL || 'http://localhost:5000'; const proxy = createProxyMiddleware({ target: API_BASE_URL, changeOrigin: true, pathRewrite: { '^/api': '/api', // 保持路径一致 }, }); export const config = { api: { bodyParser: false, // 禁用bodyParser,让代理处理请求体 externalResolver: true, }, }; export default proxy;
同理,pages/auth/[...path].js可套用相同逻辑配置。
在环境变量中设置API_BASE_URL:开发环境设为http://localhost:5000,生产环境设为http://api:5100。注意这里是服务器端API路由,无需给变量加NEXT_PUBLIC_前缀。
方案3:构建时动态生成next.config.js
写一个Node.js脚本,根据当前环境变量生成对应的next.config.js文件,再执行Next.js构建命令。
示例脚本generate-next-config.js:
const fs = require('fs'); const API_BASE_URL = process.env.API_BASE_URL || 'http://localhost:5000'; const configContent = ` const nextConfig = { reactStrictMode: true, async rewrites() { return [ { source: "/api/:path*", destination: "${API_BASE_URL}/api/:path*", }, { source: "/auth/:path*", destination: "${API_BASE_URL}/auth/:path*", }, ]; }, }; module.exports = nextConfig; `; fs.writeFileSync('next.config.js', configContent.trim());
修改package.json脚本:
{ "scripts": { "dev": "API_BASE_URL=http://localhost:5000 node generate-next-config.js && next dev", "build": "API_BASE_URL=http://api:5100 node generate-next-config.js && next build", "start": "next start" } }
这样在开发或构建前,会先根据环境变量生成正确的next.config.js,完美适配不同环境的路由重写需求。
内容的提问来源于stack exchange,提问作者Aleister Crowley

