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

非create-react-app项目客户端如何访问Node.js服务端环境变量

问题根源
  • dotenv 是Node.js服务端专属的运行时工具,仅会将.env文件内的变量注入到服务端进程的process.env对象中,浏览器环境运行的客户端代码原生不存在该对象,无法直接读取服务端进程内的变量。
  • 你能正常访问process.env.NODE_ENV,是因为各类前端构建工具默认会对该字符串做静态硬编码替换,并非客户端具备读取服务端全量环境变量的能力,其余自定义变量不会被自动替换。
  • 所有透传给客户端的环境变量必须做白名单过滤,严禁直接暴露全量process.env,避免数据库密码、接口密钥等敏感信息泄露。
可行方案

以下两个方案均不需要依赖create-react-app,也不会出现webpack安装后的大量依赖报错问题,按需选择即可。

方案1:构建时静态注入(适配原有客户端代码写法,零业务代码改动)

该方案通过轻量构建工具在打包客户端代码时,直接将指定环境变量替换为静态值,客户端代码可以继续沿用process.env.xxx的写法,不需要调整业务逻辑。

  1. 在原有服务端config.js中单独拆分客户端可访问的公开变量白名单,仅放入非敏感的客户端所需变量:
    const dotenv = require('dotenv');
    const path = require('path');
    
    dotenv.config({
        path: path.resolve(__dirname, `../environments/${process.env.NODE_ENV.trim()}.env`)
    });
    
    // 服务端自用配置,不对外暴露
    const serverConfig = {
        NODE_ENV: process.env.NODE_ENV || 'development',
        DEF_USER: process.env.DEF_USER || 'admin'
    };
    
    // 仅客户端可访问的非敏感变量,做构建替换用
    const clientDefine = {
        "process.env.NODE_ENV": JSON.stringify(serverConfig.NODE_ENV),
        "process.env.DEF_USER": JSON.stringify(serverConfig.DEF_USER)
    };
    
    module.exports = {
        ...serverConfig,
        clientDefine
    };
    
  2. 替换易报错的webpack为零配置轻量构建工具esbuild,安装依赖:
    npm install esbuild --save-dev
    
  3. 编写极简客户端构建脚本,直接引入白名单变量做注入:
    // scripts/build-client.js
    const esbuild = require('esbuild');
    const { clientDefine } = require('../config');
    
    esbuild.build({
        entryPoints: ['../client/src/index.js'], // 替换为你的客户端入口文件实际路径
        bundle: true,
        outfile: '../client/dist/bundle.js', // 替换为客户端构建产物输出路径
        define: clientDefine, // 构建时自动替换代码中对应的process.env字段
        minify: process.env.NODE_ENV === 'production'
    }).catch(() => process.exit(1));
    
  4. 后续构建客户端时直接执行node scripts/build-client.js即可,客户端代码中可直接通过process.env.DEF_USER获取对应值。

方案2:运行时接口下发(零构建配置改动,灵活度最高)

如果不想调整任何前端构建逻辑,直接通过服务端接口下发公开环境变量即可,不需要安装额外构建工具。

  1. 在服务端新增公开路由,仅返回白名单内的非敏感变量(以Express框架为例,其他框架逻辑一致):
    // 服务端路由配置
    app.get('/api/public-env', (req, res) => {
        res.json({
            DEF_USER: process.env.DEF_USER || 'admin',
            NODE_ENV: process.env.NODE_ENV || 'development'
            // 仅在此处添加客户端需要的非敏感变量,禁止传入密钥、数据库连接串等敏感配置
        })
    })
    
  2. 客户端初始化阶段先请求该接口,拿到变量后存入全局供业务代码调用:
    // 客户端入口初始化逻辑
    window.publicEnv = {};
    async function bootstrap() {
        const resp = await fetch('/api/public-env');
        window.publicEnv = await resp.json();
        // 后续业务代码通过window.publicEnv.DEF_USER即可获取对应值
        // 追加其余应用初始化逻辑
    }
    bootstrap();
    

该方案无需重新构建客户端即可生效,调整环境变量后仅需重启服务端,适合迭代频繁的场景。

避坑提示
  • 禁止在客户端代码中直接引入服务端的config.js文件,否则构建时会将服务端配置、dotenv相关依赖全部打包进客户端产物,极易造成敏感信息泄露。
  • 所有暴露给客户端的变量必须提前做白名单校验,严禁直接返回全量process.env对象。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 21:57:36