0

0

Next.js 环境变量管理:解决生产环境秘密值失效问题

霞舞

霞舞

发布时间:2025-09-20 21:54:02

|

621人浏览过

|

来源于php中文网

原创

Next.js 环境变量管理:解决生产环境秘密值失效问题

本文深入探讨 Next.js 应用中环境变量在生产环境失效的常见问题,特别是针对服务器端 API 路由。文章详细阐述了 NEXT_PUBLIC_ 前缀的正确使用场景,指出服务器端秘密值不应使用此前缀,并提供了一种通过 API 路由安全暴露公共环境变量的策略,确保应用在本地和生产环境中均能正确访问所需配置。

Next.js 应用中环境变量的挑战

在开发 next.js 单页应用(spa)时,我们经常需要使用环境变量来存储敏感信息(如 api 密钥、数据库凭证)或配置项。在本地开发环境中,通过 .env 或 .env.local 文件管理这些变量通常运行良好。然而,当应用部署到生产环境时,开发者可能会遇到环境变量无法正确加载,导致功能异常(例如,外部 api 调用失败,报错信息如“the incoming json object does not contain a client_email field”)。这通常源于对 next.js 环境变量处理机制的误解,尤其是在服务器端 api 路由中。

理解 Next.js 环境变量的前缀规则

Next.js 对环境变量的处理有明确的规则,主要通过 NEXT_PUBLIC_ 前缀来区分:

  1. NEXT_PUBLIC_ 前缀变量: 带有 NEXT_PUBLIC_ 前缀的环境变量会被注入到客户端 JavaScript bundle 中。这意味着这些变量可以在浏览器端代码中直接访问,但它们是公开的,不应包含任何敏感信息
  2. 无前缀变量: 没有 NEXT_PUBLIC_ 前缀的环境变量仅在服务器端可用。这包括 Next.js 的 Node.js 服务器环境、API 路由(pages/api 或 app/api)以及 getServerSideProps、getStaticProps 等数据获取函数。这些变量是安全的,可以存储敏感信息。

核心问题: 许多开发者误以为所有环境变量都需要 NEXT_PUBLIC_ 前缀才能在生产环境中被识别,或是在服务器端 API 路由中错误地使用了带有 NEXT_PUBLIC_ 前缀的敏感变量。

解决方案一:纠正服务器端秘密值的命名

对于需要在服务器端(例如 Next.js API 路由)使用的秘密值,如 Google API 的 client_email 和 private_key,它们不应该带有 NEXT_PUBLIC_ 前缀。因为 API 路由运行在服务器端,这些变量应该被视为服务器端变量。

错误的配置示例(导致生产环境失效):

# .env 或生产环境配置中
NEXT_PUBLIC_GOOGLE_CLIENT_EMAIL=your-client-email@project.iam.gserviceaccount.com
NEXT_PUBLIC_GOOGLE_PRIVATE_KEY=-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n
NEXT_PUBLIC_GOOGLE_SHEET_ID=your-sheet-id

正确的配置示例(适用于服务器端 API 路由):

# .env 或生产环境配置中
GOOGLE_CLIENT_EMAIL=your-client-email@project.iam.gserviceaccount.com
GOOGLE_PRIVATE_KEY=-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n
GOOGLE_SHEET_ID=your-sheet-id

修改 submit.js API 路由文件:

在 API 路由中,直接通过 process.env 访问这些无前缀的变量:

import { google } from 'googleapis';

// 移除 dotenv-flow,在 Next.js 环境中通常不需要手动配置
// require('dotenv-flow').config()

export default async function handler(req, res) {
  if (req.method !== 'POST') {
    return res.status(405).send('Only POST requests are allowed!');
  }

  const body = req.body;

  try {
    const auth = new google.auth.GoogleAuth({
      credentials: {
        // 直接访问无 NEXT_PUBLIC_ 前缀的变量
        client_email: process.env.GOOGLE_CLIENT_EMAIL,
        private_key: process.env.GOOGLE_PRIVATE_KEY?.replace(/\\n/g, '\n'),
      },
      scopes: [
        'https://www.googleapis.com/auth/drive',
        'https://www.googleapis.com/auth/drive.file',
        'https://www.googleapis.com/auth/spreadsheets',
      ],
    });
    const sheets = google.sheets({
      auth,
      version: 'v4',
    });

    const submittedAt = new Date().toUTCString();

    const response = await sheets.spreadsheets.values.append({
      spreadsheetId: process.env.GOOGLE_SHEET_ID, // 同样访问无 NEXT_PUBLIC_ 前缀的变量
      range: 'A1:F1',
      valueInputOption: 'USER_ENTERED',
      requestBody: {
        values: [
          [
            body.name,
            body.company,
            body.product,
            body.email,
            body.phone,
            submittedAt,
          ],
        ],
      },
    });

    return res.status(201).json({
      data: response.data,
    });
  } catch (error) {
    console.error('Google Sheets API error:', error); // 使用 console.error 记录错误
    // 错误处理时,避免直接暴露敏感信息,但可以记录错误详情
    return res.status(error.code || 500).send({ message: error.message || 'An unexpected error occurred.' });
  }
}

通过移除 NEXT_PUBLIC_ 前缀,这些变量将只在服务器端可用,从而解决了“client_email field missing”的错误,并增强了安全性。

解决方案二:通过 API 路由安全地暴露公共环境变量(如果需要)

虽然服务器端秘密值不应带有 NEXT_PUBLIC_ 前缀,但有时客户端确实需要访问一些公共的配置变量,例如 Google Tag Manager (GTM) ID,这些变量理应带有 NEXT_PUBLIC_ 前缀。如果这些 NEXT_PUBLIC_ 变量在生产环境中仍无法加载,或者出于某种原因需要在运行时动态获取,可以通过创建一个专门的 API 路由来暴露它们。

PictoGraphic
PictoGraphic

AI驱动的矢量插图库和插图生成平台

下载

创建 pages/api/env.js 文件:

// pages/api/env.js
export default function handler(req, res) {
  // 过滤出所有以 'NEXT_PUBLIC_' 开头的环境变量
  const publicEnv = Object.keys(process.env)
    .filter((key) => key.startsWith('NEXT_PUBLIC_'))
    .reduce((acc, key) => {
      acc[key] = process.env[key];
      return acc;
    }, {});

  // 返回 JSON 格式的公共环境变量
  res.status(200).json(publicEnv);
}

客户端如何访问这些变量:

在客户端组件中,可以通过 fetch 请求调用这个 API 路由来获取公共环境变量:

// 例如,在某个 React 组件中
import React, { useEffect, useState } from 'react';

function MyComponent() {
  const [envVars, setEnvVars] = useState({});

  useEffect(() => {
    async function fetchEnvVars() {
      try {
        const response = await fetch('/api/env');
        const data = await response.json();
        setEnvVars(data);
      } catch (error) {
        console.error('Failed to fetch public environment variables:', error);
      }
    }
    fetchEnvVars();
  }, []);

  // 现在可以在组件中使用 envVars.NEXT_PUBLIC_GTM_ID 等变量
  return (
    

GTM ID: {envVars.NEXT_PUBLIC_GTM_ID || 'Loading...'}

{/* ... 其他使用公共变量的代码 */}
); } export default MyComponent;

这种方法提供了一个健壮的机制,确保客户端能够访问所需的公共配置,即使在构建时注入的环境变量出现问题,或者需要动态更新这些变量时。

部署环境中的环境变量管理

无论是在 Docker、AWS、Vercel 还是其他云平台上部署 Next.js 应用,生产环境中的环境变量都应通过平台提供的安全机制进行配置,而不是直接提交到代码仓库或依赖 .env.local 文件。

  • Vercel: 在项目设置中配置环境变量。
  • AWS ECS/Lambda: 通过任务定义或 Lambda 函数配置环境变量。
  • Docker: 使用 Docker Compose 的 environment 字段或 docker run -e 命令注入环境变量。

确保这些环境变量在部署时被正确注入到 Next.js 运行时环境中至关重要。

总结与最佳实践

  1. 区分服务器端与客户端变量:
    • 服务器端秘密值(如 API 密钥): 不要使用 NEXT_PUBLIC_ 前缀,仅在服务器端(API 路由、getServerSideProps 等)访问。
    • 客户端公共值(如 GTM ID): 使用 NEXT_PUBLIC_ 前缀,它们会被打包到客户端代码中。
  2. 安全性优先: 永远不要将敏感信息(如私钥)直接暴露给客户端。
  3. 生产环境配置: 避免依赖 .env.local 文件在生产环境工作。使用部署平台提供的环境变量管理工具。
  4. 动态获取公共变量: 如果 NEXT_PUBLIC_ 变量在客户端无法正常加载,或者需要更灵活的配置管理,可以考虑通过 API 路由动态获取。

遵循这些原则,可以有效避免 Next.js 应用在生产环境中因环境变量配置不当而导致的问题,确保应用稳定、安全地运行。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
json数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

418

2023.08.07

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

535

2023.08.23

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

311

2023.10.13

go语言处理json数据方法
go语言处理json数据方法

本专题整合了go语言中处理json数据方法,阅读专题下面的文章了解更多详细内容。

77

2025.09.10

lambda表达式
lambda表达式

Lambda表达式是一种匿名函数的简洁表示方式,它可以在需要函数作为参数的地方使用,并提供了一种更简洁、更灵活的编码方式,其语法为“lambda 参数列表: 表达式”,参数列表是函数的参数,可以包含一个或多个参数,用逗号分隔,表达式是函数的执行体,用于定义函数的具体操作。本专题为大家提供lambda表达式相关的文章、下载、课程内容,供大家免费下载体验。

207

2023.09.15

python lambda函数
python lambda函数

本专题整合了python lambda函数用法详解,阅读专题下面的文章了解更多详细内容。

191

2025.11.08

Python lambda详解
Python lambda详解

本专题整合了Python lambda函数相关教程,阅读下面的文章了解更多详细内容。

53

2026.01.05

js正则表达式
js正则表达式

php中文网为大家提供各种js正则表达式语法大全以及各种js正则表达式使用的方法,还有更多js正则表达式的相关文章、相关下载、相关课程,供大家免费下载体验。

513

2023.06.20

俄罗斯Yandex引擎入口
俄罗斯Yandex引擎入口

2026年俄罗斯Yandex搜索引擎最新入口汇总,涵盖免登录、多语言支持、无广告视频播放及本地化服务等核心功能。阅读专题下面的文章了解更多详细内容。

158

2026.01.28

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 4.3万人学习

国外Web开发全栈课程全集
国外Web开发全栈课程全集

共12课时 | 1.0万人学习

React核心原理新老生命周期精讲
React核心原理新老生命周期精讲

共12课时 | 1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号