一、安装cross-env
1、解决方案一
直接设置公开变量:
{
"dev": "cross-env NEXT_PUBLIC_APP_ENV=development next dev -p 4400",
"dev:test": "cross-env NEXT_PUBLIC_APP_ENV=test next dev -p 4400",
"build:prod": "cross-env NEXT_PUBLIC_APP_ENV=production next build"
}
然后:
process.env.NEXT_PUBLIC_APP_ENV
就会得到:
development
test
production
2、解决方案二(推荐)
脚本:
{
"dev": "cross-env APP_ENV=development next dev",
"dev:test": "cross-env APP_ENV=test next dev",
"build:prod": "cross-env APP_ENV=production next build"
}
然后在 next.config.ts:
import type { NextConfig } from 'next';
const APP_ENV = process.env.APP_ENV ?? 'development';
console.log('APP_ENV=', APP_ENV);
const nextConfig: NextConfig = {
env: {
NEXT_PUBLIC_APP_ENV: APP_ENV,
},
};
export default nextConfig;
重启开发服务器。
此时:
pnpm dev:test
控制台:
APP_ENV=test
浏览器:
process.env.NEXT_PUBLIC_APP_ENV
↓
test
3、如果仍然显示 development
检查 .env.development 是否有:
NEXT_PUBLIC_APP_ENV=development
因为 next.config.ts 的 env 配置和 .env 文件可能会同时存在。
最简单的做法是:
删除所有 .env* 文件里的 NEXT_PUBLIC_APP_ENV
只保留:
NEXT_PUBLIC_API_URL=...
然后统一由:
// next.config.ts
env: {
NEXT_PUBLIC_APP_ENV: APP_ENV,
}
生成。
这样不会出现:
.env.development => development
cross-env => test
两个来源打架的问题。
二、根据 APP_ENV 注入对应的 API 地址
const config = {
development: {
apiUrl: 'https://dev-api.example.com',
},
test: {
apiUrl: 'https://test-api.example.com',
},
production: {
apiUrl: 'https://api.example.com',
},
};
const APP_ENV = process.env.APP_ENV ?? 'development';
export default {
env: {
NEXT_PUBLIC_APP_ENV: APP_ENV,
NEXT_PUBLIC_API_URL: config[APP_ENV].apiUrl,
},
};
这样:
process.env.NEXT_PUBLIC_API_URL
才会随着:
pnpm dev
pnpm dev:test
pnpm build:prod
自动切换。
对于 Next.js 项目,我通常会把所有环境配置集中到 src/config/env.ts,并通过 APP_ENV → next.config.ts → NEXT_PUBLIC_* 这一层映射来管理,而不是在多个 .env 文件里维护同一套前端配置。这样类型更安全,也更容易排查问题。
三、配置端口以及开发启动打开默认浏览器
先安装:
pnpm add -D concurrently wait-on open-cli
然后修改 package.json:
{
"scripts": {
"dev": "concurrently \"next dev -p 4400\" \"wait-on http://localhost:4400 && open-cli http://localhost:4400\"",
"dev:test": "concurrently \"cross-env APP_ENV=test next dev -p 4400\" \"wait-on http://localhost:4400 && open-cli http://localhost:4400\""
}
}
启动:
pnpm dev
或者:
pnpm dev:test
服务启动完成后会自动打开默认浏览器访问:
http://localhost:4400
为了避免端口写两遍,推荐抽成变量:
{
"scripts": {
"dev": "cross-env PORT=4400 concurrently \"next dev -p %PORT%\" \"wait-on http://localhost:%PORT% && open-cli http://localhost:%PORT%\""
}
}
但这在 Windows 和 macOS/Linux 上变量写法不同,所以实际项目里很多人直接写死:
{
"scripts": {
"dev": "concurrently \"next dev -p 4400\" \"wait-on http://localhost:4400 && open-cli http://localhost:4400\""
}
}
最简单也最稳定。
如果你已经有开发、测试、生产环境脚本,我推荐这样整理:
{
"scripts": {
"dev": "concurrently \"cross-env APP_ENV=development next dev -p 4400\" \"wait-on http://localhost:4400 && open-cli http://localhost:4400\"",
"dev:test": "concurrently \"cross-env APP_ENV=test next dev -p 4400\" \"wait-on http://localhost:4400 && open-cli http://localhost:4400\"",
"build:test": "cross-env APP_ENV=test next build",
"build:prod": "cross-env APP_ENV=production next build",
"start:test": "cross-env APP_ENV=test next start -p 4400",
"start:prod": "cross-env APP_ENV=production next start -p 4400"
}
}
这样执行 pnpm dev 或 pnpm dev:test 时都会自动打开浏览器。