Skip to content

Next.js 环境变量

环境变量

NEXT_PUBLIC_ 开头的环境变量才能被客户端访问,其他环境变量只能在服务端使用。

NOTE

我们注意到,客户端也可以直接访问 process.env.NEXT_PUBLIC_XXX,因为 Next.js 会在构建时将这些代码替换为内联值,因此它们也不能在构建之后改变。

这种替换方法不能用于动态访问,例如客户端不能使用下面的代码:

ts
const varName = 'NEXT_PUBLIC_ANALYTICS_ID'
setupAnalyticsService(process.env[varName])

const env = process.env
setupAnalyticsService(env.NEXT_PUBLIC_ANALYTICS_ID)

在服务端,我们可以通过 process.env.NODE_ENV 来判断当前环境,开发环境为 'development',而生产环境为 'production'

如果我们希望在客户端也能获取到当前环境,则需要自定义环境变量。我们可以通过在 .env.development 文件中添加 NEXT_PUBLIC_ENV=development 来实现。然后我们读取 process.env.NEXT_PUBLIC_ENV 来获取当前环境。

如果我们希望自定义一种环境,比如 staging 或者 preview,则它最好由 development 衍生,这样我们可以在开发环境中模拟这种环境。

构建时

还有一种特殊的状态,叫做构建时(buildtime),这和运行时(runtime)或生产环境有一些不同,例如当我们的服务端页面需要预渲染时,我们需要在构建时生成静态页面。

在 Next.js 中,我们可以通过 process.env.NEXT_PHASE 来判断当前是否为构建时,为 true 则表示为构建时。

例如,当我们需要使用 Redis 时,我们一般这么用:

ts
import { createClient } from 'redis'

export const redisClient = createClient({
  url: process.env.REDIS_URL,
})
await redisClient.connect()

构建时需要生产环境的 Redis 地址,而构建时未必能连接到生产环境的 Redis,如果这个时候构建会一直尝试连接直至失败(因为 Next.js 会在构建时执行你的代码)。这时候我们加上判断:

ts
import { createClient } from 'redis'

export const redisClient = createClient({
  url: process.env.REDIS_URL,
})
if (!process.env.NEXT_PHASE) {
  await redisClient.connect()
} else {
  console.warn('[Redis] building now, skip connecting!')
}

这在 Docker 这种隔离的构建环境中很有用。当然也可以在这个时候连接到其他可用 Redis 服务器。