You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

生产环境中Next.js前端无法访问Cloud Run配置的环境变量

解决Cloud Run环境变量在Next.js客户端无法访问的问题

你踩中了Next.js环境变量的一个关键机制坑——NEXT_PUBLIC_前缀的变量是在构建阶段被静态嵌入客户端代码的,而你的流程是先构建镜像(此时还没有Cloud Run配置的环境变量),之后再在Cloud Run里设置变量,这就导致客户端代码里根本没有这些变量的痕迹,自然返回undefined。本地测试正常是因为你构建时本地.env文件提供了这些变量。

针对你的需求(同一个镜像多实例,动态注入不同环境变量),给你两个直接可行的解决方案:

方案一:通过SSR传递运行时环境变量(推荐)

这个方案利用getServerSideProps在每次请求时从服务端读取环境变量,再传递给客户端组件,完全适配你动态注入的需求:

  1. 清理next.config.js的冗余配置
    删掉和NEXT_PUBLIC_FIREBASE_USER_ID相关的envpublicRuntimeConfigserverRuntimeConfig配置,同时移除Dotenv插件(生产环境不需要加载本地.env):

    module.exports = withPlugins(plugins, {
      assetPrefix,
      reactStrictMode: true,
      eslint: {
        ignoreDuringBuilds: true,
      },
      async rewrites() {
        return [
          { source: '/:any*', destination: '/', },
        ];
      },
    });
    
  2. 修改getServerSideProps传递变量
    直接在服务端读取环境变量(不需要NEXT_PUBLIC_前缀),然后作为props传给客户端:

    export async function getServerSideProps() {
      return {
        props: {
          uid: process.env.FIREBASE_USER_ID,
          storeId: process.env.FIREBASE_STORE_ID
        }
      }
    }
    
  3. 客户端组件直接使用props
    不需要再用getConfig(),直接从组件props里拿值:

    function App({ uid, storeId }) {
      useEffect(() => {
        console.log("FIREBASE_USER_ID: ", uid)
        console.log("FIREBASE_STORE_ID: ", storeId)
      }, [])
      return <Routes />;
    }
    

这样每次Cloud Run实例启动时,服务端会读取你配置的环境变量,请求时自动传递给客户端,后续修改Cloud Run的环境变量后,只要重启实例就能生效。

方案二:通过自定义API路由暴露环境变量

如果你的页面是静态生成(SSG)的,或者不想依赖SSR,可以创建一个API路由来返回环境变量:

  1. 创建pages/api/env.js

    export default function handler(req, res) {
      // 只返回需要暴露给客户端的变量,避免敏感信息泄露
      res.status(200).json({
        firebaseUserId: process.env.FIREBASE_USER_ID,
        firebaseStoreId: process.env.FIREBASE_STORE_ID
      })
    }
    
  2. 客户端组件请求API获取变量

    import { useState, useEffect } from 'react'
    
    function App() {
      const [envVars, setEnvVars] = useState(null)
    
      useEffect(() => {
        async function fetchEnv() {
          const response = await fetch('/api/env')
          const data = await response.json()
          setEnvVars(data)
          console.log("FIREBASE_USER_ID: ", data.firebaseUserId)
        }
        fetchEnv()
      }, [])
    
      if (!envVars) return <div>Loading...</div>
      return <Routes />;
    }
    

额外注意事项

  • Cloud Run环境变量配置:去掉变量名的NEXT_PUBLIC_前缀,直接用FIREBASE_USER_IDFIREBASE_STORE_ID
  • Dockerfile优化runner阶段可以只复制package.jsonyarn.lock,然后执行yarn install --production,减少镜像体积(这步不影响环境变量问题,但能优化部署)。
  • 敏感信息防护:不要把敏感环境变量暴露给客户端,只传递业务需要的非敏感变量。

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

火山引擎 最新活动