You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React部署Firebase后无法读取REACT_APP_DB_API密钥的问题

React部署Firebase后无法读取环境密钥的解决方案

问题背景

我的React应用本地运行正常,通过const currentDBAPI = process.env.REACT_APP_DB_API能正常读取密钥。但部署到Firebase后,React读取密钥时报错:SyntaxError: Unexpected token '<', "<!doctype "... is not valid JSON。

已尝试的操作:

  • 参考Firebase相关文档的Secret Manager流程,但该流程针对NodeJS服务端,安装firebase-functions包后,GitHub Actions部署时出现Module not found: Error: Can't resolve 'async_hooks' in '.../firebase-functions/lib/common'错误,安装async_hooks后问题依旧,后得知该包为NodeJS服务端专用。
  • 在GitHub Actions构建步骤中添加密钥配置,但问题仍未解决:
steps:
      - uses: actions/checkout@v3
      - run: yarn install --frozen-lockfile && yarn build
        env: 
          REACT_APP_DB_API: '${{ secrets.REACT_APP_DB_API }}'
      - uses: FirebaseExtended/action-hosting-deploy@v0
        with:
          repoToken: '${{ secrets.GITHUB_TOKEN }}'
          firebaseServiceAccount: '${{ secrets.FIREBASE_SERVICE_ACCOUNT_project-id }}'
          projectId: my-project-id

核心原因

React是前端单页应用,构建后会将环境变量打包进静态文件,无法在运行时直接读取Firebase Secret Manager的密钥,也不能通过服务端的firebase-functions处理前端变量。你遇到的报错,是因为代码误将HTML页面内容(<!doctype开头)当作JSON解析,大概率是读取密钥的逻辑出错,把变量当成API地址发起了请求。

正确解决步骤

1. 确认构建时环境变量注入逻辑

你的GitHub Actions配置方向正确,但需注意两点:

  • 确保GitHub仓库的Secrets中已正确添加REACT_APP_DB_API,密钥值无误。
  • 构建命令(yarn build)必须在注入环境变量的步骤中执行——Create React App会在构建阶段,将所有前缀为REACT_APP_的变量嵌入到静态代码中。

2. 修正代码中读取变量的逻辑

确保没有在运行时发起请求获取该密钥,正确写法是直接引用变量:

const currentDBAPI = process.env.REACT_APP_DB_API;
// 直接使用变量,不要用fetch/axios发起请求

3. 验证构建产物

本地测试构建时的变量注入效果:

REACT_APP_DB_API=你的测试密钥 yarn build

打开构建后的build/static/js/main.*.js文件,搜索REACT_APP_DB_API,确认密钥已被替换到代码中。注意:此方式会将密钥明文打包进前端代码,仅适用于非敏感密钥(如公开的API调用密钥);若为敏感密钥(如数据库密码),必须通过Firebase Functions中转。

4. 敏感密钥的中转方案

如果REACT_APP_DB_API是敏感密钥,需通过Firebase Functions做中间层:

  • 编写一个Firebase Function作为API代理,在服务端读取Secret Manager的密钥,再转发请求到目标DB API。
  • React前端仅请求该Function的地址,不直接接触敏感密钥。

示例Function代码:

const functions = require("firebase-functions");
const { SecretManagerServiceClient } = require("@google-cloud/secret-manager");
const client = new SecretManagerServiceClient();

exports.proxyDBAPI = functions.https.onRequest(async (req, res) => {
  // 从Secret Manager获取密钥
  const [version] = await client.accessSecretVersion({
    name: "projects/你的项目ID/secrets/REACT_APP_DB_API/versions/latest",
  });
  const dbApiKey = version.payload.data.toString();
  
  // 转发请求到目标DB API,携带密钥
  const response = await fetch("https://你的DBAPI地址/endpoint", {
    headers: { "Authorization": `Bearer ${dbApiKey}` }
  });
  const data = await response.json();
  res.send(data);
});

React前端请求示例:

const fetchData = async () => {
  const response = await fetch("/proxyDBAPI");
  const data = await response.json();
  // 处理返回数据
};

内容的提问来源于stack exchange,提问作者MadeInDreams

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 13:35:06