Angular 19 + Nx 单仓项目中dotenv环境变量替换配置缺失问题排查
你碰到的这个问题其实是Angular/Nx项目里用dotenv类工具的常见坑——浏览器环境根本没有process这个Node.js全局对象,直接在environment.ts里写process.env['SOME_API_KEY'],不管你用dotenvx还是什么,运行时浏览器都认不出来。而且Vite(现在Nx Angular默认用Vite构建)会把Node相关模块比如process标记为外部依赖,不让你在客户端代码里直接引用,这就是为什么你导入process后会看到那个“模块已外部化”的错误。
下面我一步步给你拆解解决方案:
第一步:修正environment.ts的写法,别直接用process.env
先把你的src/environments/environment.ts改成符合浏览器环境的写法,这里推荐用Vite官方支持的import.meta.env(编译时会自动替换成实际变量值),示例:
export const env = { someApi: "https://some.tld/api/v1/", // 用Vite支持的import.meta.env,后面加默认值方便本地开发 someApiKey: import.meta.env.VITE_SOME_API_KEY || "local-dev-key", anotherApiKey: import.meta.env.VITE_ANOTHER_API_KEY || "local-dev-key" };
第二步:调整环境变量的命名规则(或配置Vite兼容原有命名)
Vite默认只会自动识别前缀为VITE_的环境变量,所以你需要二选一:
方案A:给.env文件的变量加VITE_前缀(推荐,符合Vite规范)
修改你的apps/some-app/.env、.env.uat、.env.prod:
VITE_SOME_API_KEY="123-API-456-KEY-789" VITE_ANOTHER_API_KEY="123-API-456-KEY-789"
方案B:配置Vite兼容原有变量名(不推荐,多一步配置)
如果不想改变量名,就在apps/some-app/vite.config.ts里添加define配置,让Vite在编译时把process.env的变量替换成实际值:
import { defineConfig } from 'vite'; import angular from '@nx/angular/plugins/vite'; export default defineConfig({ plugins: [angular()], define: { // 把dotenvx注入的变量映射成全局常量,编译时替换 'process.env.SOME_API_KEY': JSON.stringify(process.env.SOME_API_KEY || "local-dev-key"), 'process.env.ANOTHER_API_KEY': JSON.stringify(process.env.ANOTHER_API_KEY || "local-dev-key") } });
这种情况下你可以继续用process.env['SOME_API_KEY']的写法,但本质上是Vite在编译时把它替换成了字符串,浏览器运行时根本看不到process。
第三步:修正package.json的脚本(两个关键细节)
我看你的脚本里有两个小问题,必须改:
- 命令参数的空格:
nx build some-app--configuration production里的some-app和--configuration之间少了空格,Nx会把它当成一个错误的项目名 watch:some-app没加dotenvx,本地开发时变量不会被注入
修正后的脚本:
"scripts": { "start:some-app": "dotenvx run -f apps/some-app/.env -- nx serve some-app", "build:some-app": "dotenvx run -f apps/some-app/.env.prod -- nx build some-app --configuration production", "build:some-app:uat": "dotenvx run -f apps/some-app/.env.uat -- nx build some-app --configuration uat", "watch:some-app": "dotenvx run -f apps/some-app/.env -- nx build some-app --watch --configuration development", "test:some-app": "nx test some-app", "coverage:some-app": "nx test some-app --no-watch --code-coverage" }
第四步:给TypeScript加类型声明(避免红色波浪线)
如果用import.meta.env的方案,TypeScript可能会报类型错误,你可以在src/env.d.ts里添加类型声明:
interface ImportMetaEnv { readonly VITE_SOME_API_KEY: string; readonly VITE_ANOTHER_API_KEY: string; } interface ImportMeta { readonly env: ImportMetaEnv; }
如果用process.env的方案,就在src/types/process.d.ts里加:
declare namespace NodeJS { interface ProcessEnv { readonly SOME_API_KEY: string; readonly ANOTHER_API_KEY: string; } }
然后在tsconfig.app.json的compilerOptions.types里包含这个类型文件。
最后验证
运行npm run start:some-app,打开浏览器控制台打印env.someApiKey,应该能看到.env里的实际值,再也不会出现process is not defined的错误了。
内容来源于stack exchange

