JS项目前端读取根目录.env环境变量返回undefined问题
问题场景
项目根目录下同时存放前端代码目录frontend、服务端代码目录server以及全局环境变量配置文件.env,目录结构如下:
project ├─ frontend ├─ server └─ .env
实际运行表现:
- 服务端代码中通过
process.env.PORT可以正常读取.env中配置的端口值 - 前端代码中通过
process.env['PORT']读取变量时返回undefined - 编辑器输入变量名时可正常弹出代码提示,但浏览器控制台实际打印结果仍为
undefined
根本原因
process是Node.js运行时提供的全局对象,浏览器原生环境中不存在这个对象。
服务端代码直接运行在Node环境中,配合dotenv等库加载根目录的.env文件后,自然可以正常读取挂载在process.env上的变量。
前端代码最终运行在浏览器环境中,代码里写的process.env相关逻辑,本质是构建工具(Vite、Webpack、Create React App等)在编译打包阶段做的静态文本替换,并非运行时真的能访问Node环境的process对象:
- 编辑器弹出代码提示,只是因为TS/JS语法服务识别到了Node类型的类型定义,和代码运行时的实际逻辑无关
- 构建工具默认不会主动加载前端目录之外的
.env文件,也不会把process.env上的所有变量都注入前端打包产物,这个设计是为了避免把服务端用的敏感密钥泄露到公开的前端代码中。
解决方案
注意:所有注入前端的环境变量都会明文打包进前端JS产物,任何访问站点的用户都可以在浏览器源码中直接看到,绝对不要把数据库密码、服务端密钥这类敏感信息存在前端可读取的环境变量中。
按所用构建工具的约定配置环境变量(推荐)
不要把前后端的环境变量全混在根目录的.env里,优先按工具约定存放和命名变量,从根源避免敏感信息泄露:
- 如果使用Vite构建:
- 前端需要读取的变量必须以
VITE_作为前缀,比如将端口配置写为VITE_PORT=3000 - 前端代码中通过
import.meta.env.VITE_PORT读取变量,不要使用process.env - 如果确实要复用根目录的
.env文件,可以在frontend/vite.config.js中配置env路径指向根目录:import { defineConfig } from 'vite' export default defineConfig({ envDir: '../' // 指向frontend目录的上一级,即项目根目录 })
- 前端需要读取的变量必须以
- 如果使用Create React App(CRA)/原生Webpack构建:
- 前端需要读取的变量必须以
REACT_APP_作为前缀,比如将端口配置写为REACT_APP_PORT=3000 - 前端代码中通过
process.env.REACT_APP_PORT读取变量 - 推荐将前端专用的公共环境变量放在
frontend/.env文件中,和服务端变量物理隔离,避免误泄露。如果确实要加载根目录的.env,可以在构建配置中通过dotenv手动指定env文件路径即可。
- 前端需要读取的变量必须以
自定义构建配置注入指定变量
如果是自定义Webpack配置,可以通过DefinePlugin手动声明需要注入前端的环境变量,只注入需要的字段即可,不要全量注入:
// webpack.config.js const webpack = require('webpack') const dotenv = require('dotenv') // 加载项目根目录下的.env配置 const envConfig = dotenv.config({ path: '../.env' }).parsed module.exports = { // 其他配置... plugins: [ new webpack.DefinePlugin({ 'process.env.PORT': JSON.stringify(envConfig.PORT) }) ] }
内容的提问来源于stack exchange,提问作者Alexandra Danilevich
相关产品推荐
相关产品推荐

