process.env 未定义 - NestJS
process.env's are undefined - NestJS
我决定在这里写,因为我 运行 没有想法。我有一个 NestJS 应用程序,我在其中使用了 env - 没有什么不寻常的。但是当我想使用它们时,st运行ge 发生了。我也有自己的这些值的解析器,returns 它们在一个方便的对象中 - 这是第一个文件:
env.ts
const parseStringEnv = (name: string) => {
const value: string = process.env[name];
if (!value) {
throw new Error(`Invalid env ${name}`);
}
return value;
};
const parseIntEnv = (name: string) => {
const value: string = process.env[name];
const int: number = parseInt(value);
if (isNaN(int)) {
throw new Error(`Invalid env ${name}`);
}
return int;
};
const parseBoolEnv = (name: string) => {
const value: string = process.env[name];
if (value === "false") {
return false;
}
if (value === "true") {
return true;
}
throw new Error(`Invalid env ${name}`);
};
const parseMongoString = (): string => {
const host = parseStringEnv("DATABASE_HOST");
const port = parseStringEnv("DATABASE_PORT");
const user = parseStringEnv("DATABASE_USER");
const pwd = parseStringEnv("DATABASE_PWD");
const dbname = parseStringEnv("DATABASE_NAME");
return `mongodb://${user}:${pwd}@${host}:${port}/${dbname}?authSource=admin&ssl=false`;
};
export const env = {
JWT_SECRET: parseStringEnv("JWT_SECRET"),
PORT_BACKEND: parseIntEnv("PORT_BACKEND"),
CLIENT_HOST: parseStringEnv("CLIENT_HOST"),
ENABLE_CORS: parseBoolEnv("ENABLE_CORS"),
MONGO_URI: parseMongoString(),
};
export type Env = typeof env;
我想用它来设置应用程序运行的端口以及 Mongoose 的连接参数:
在main.ts中:
<rest of the code>
await app.listen(env.PORT_BACKEND || 8080);
<rest of the code>
现在,神奇的事情从这里开始 - 当仅导入 ConfigModule
时,应用程序可以正常启动。它也将在没有 ConfigModule
和添加 require('doting').config()
的情况下开始。当我添加 MongooseModule
时,应用程序崩溃,因为它无法解析 env - 最棒的是抛出的异常与用于创建 MONGO_URI
的 env 无关!!我从解析器中得到“Invalid env JWT_SECRET
”。
在app.module.ts
import { Module } from "@nestjs/common";
import { ConfigModule } from "@nestjs/config";
import { MongooseModule } from "@nestjs/mongoose";
import { AppController } from "./app.controller";
import { env } from "./common/env";
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
}),
MongooseModule.forRoot(env.MONGO_URI), //WTF?
],
controllers: [AppController],
})
export class AppModule {}
老实说,我只是 运行 不知道哪里出了问题。解析器在我的上一个项目中工作得很好(但我没有使用 Mongoose,所以这可能是导致问题的原因)。下面是我的 .env 文件模板。
JWT_SECRET=
ENABLE_CORS=
PORT_BACKEND=
DATABASE_HOST=
DATABASE_PORT=
DATABASE_USER=
DATABASE_PWD
DATABASE_NAME=
CLIENT_HOST=
感谢所有花时间帮助我的人 ;)
您正在导入 env.ts
之前 ConfigModule 已导入并在您的 .env
文件中设置变量。
这就是调用 require('dotenv').config()
有效的原因。在幕后,这就是 ConfigModule 为您所做的。但是,您对 ConfigModule.forRoot
的调用发生在 在您导入 env.ts
之后 ,因此尚未导入 .env
文件并且那些变量没有尚不存在。
我强烈建议您查看 custom configuration files,它以“嵌套方式”为您处理此问题:
来自 Nest 文档,但请注意,您也可以使用已有的 env.ts
文件:
// env.ts
export default () => ({
// Add your own properties here however you'd like
port: parseInt(process.env.PORT, 10) || 3000,
database: {
host: process.env.DATABASE_HOST,
port: parseInt(process.env.DATABASE_PORT, 10) || 5432
}
});
然后将您的 AppModule 修改为以下内容。请注意,我们正在使用 forRootAsync 以便我们可以获得 ConfigService 的句柄并从中获取变量。
// app.module.ts
import configuration from './common/env';
@Module({
imports: [
ConfigModule.forRoot({
load: [configuration],
}),
//
MongooseModule.forRootAsync({
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => ({
uri: configService.get<string>('MONGO_URI'),
}),
inject: [ConfigService],
});
],
})
export class AppModule {}
作为替代方案,您也可以在顶部的 env.ts
文件中调用 require('dotenv').config()
,但您会错过所有 ConfigModule 助手,例如 dev/prod .env
个文件。
在我的例子中,我将@types/node 降级为与我的节点版本相同的版本。可能是一个提示。
在我的例子中只需要更换订单导入模块。
import { Module } from "@nestjs/common";
import { ConfigModule } from "@nestjs/config";
import { MongooseModule } from "@nestjs/mongoose";
import { AppController } from "./app.controller";
import { env } from "./common/env"; // call process.env.xxx here > undefined
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
}), // process.env.xxx must be called after this line
MongooseModule.forRoot(env.MONGO_URI),
],
controllers: [AppController],
})
export class AppModule {}
所以修复
import { Module } from "@nestjs/common";
import { ConfigModule } from "@nestjs/config";
// should place this at very first line
const envModule = ConfigModule.forRoot({
isGlobal: true,
})
import { MongooseModule } from "@nestjs/mongoose";
import { AppController } from "./app.controller";
import { env } from "./common/env";
@Module({
imports: [
envModule,
MongooseModule.forRoot(env.MONGO_URI),
],
controllers: [AppController],
})
export class AppModule {}
通过使用 JWT 模块的 registerAsync 并读取 process.env 内部的 useFactory 方法对我有用
@Module({
imports: [
JwtModule.registerAsync({
useFactory: () => ({
secret: process.env.JWT_SECRET_KEY,
signOptions: { expiresIn: 3600 },
}),
})
],
controllers: [AppController],
})
我决定在这里写,因为我 运行 没有想法。我有一个 NestJS 应用程序,我在其中使用了 env - 没有什么不寻常的。但是当我想使用它们时,st运行ge 发生了。我也有自己的这些值的解析器,returns 它们在一个方便的对象中 - 这是第一个文件:
env.ts
const parseStringEnv = (name: string) => {
const value: string = process.env[name];
if (!value) {
throw new Error(`Invalid env ${name}`);
}
return value;
};
const parseIntEnv = (name: string) => {
const value: string = process.env[name];
const int: number = parseInt(value);
if (isNaN(int)) {
throw new Error(`Invalid env ${name}`);
}
return int;
};
const parseBoolEnv = (name: string) => {
const value: string = process.env[name];
if (value === "false") {
return false;
}
if (value === "true") {
return true;
}
throw new Error(`Invalid env ${name}`);
};
const parseMongoString = (): string => {
const host = parseStringEnv("DATABASE_HOST");
const port = parseStringEnv("DATABASE_PORT");
const user = parseStringEnv("DATABASE_USER");
const pwd = parseStringEnv("DATABASE_PWD");
const dbname = parseStringEnv("DATABASE_NAME");
return `mongodb://${user}:${pwd}@${host}:${port}/${dbname}?authSource=admin&ssl=false`;
};
export const env = {
JWT_SECRET: parseStringEnv("JWT_SECRET"),
PORT_BACKEND: parseIntEnv("PORT_BACKEND"),
CLIENT_HOST: parseStringEnv("CLIENT_HOST"),
ENABLE_CORS: parseBoolEnv("ENABLE_CORS"),
MONGO_URI: parseMongoString(),
};
export type Env = typeof env;
我想用它来设置应用程序运行的端口以及 Mongoose 的连接参数:
在main.ts中:
<rest of the code>
await app.listen(env.PORT_BACKEND || 8080);
<rest of the code>
现在,神奇的事情从这里开始 - 当仅导入 ConfigModule
时,应用程序可以正常启动。它也将在没有 ConfigModule
和添加 require('doting').config()
的情况下开始。当我添加 MongooseModule
时,应用程序崩溃,因为它无法解析 env - 最棒的是抛出的异常与用于创建 MONGO_URI
的 env 无关!!我从解析器中得到“Invalid env JWT_SECRET
”。
在app.module.ts
import { Module } from "@nestjs/common";
import { ConfigModule } from "@nestjs/config";
import { MongooseModule } from "@nestjs/mongoose";
import { AppController } from "./app.controller";
import { env } from "./common/env";
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
}),
MongooseModule.forRoot(env.MONGO_URI), //WTF?
],
controllers: [AppController],
})
export class AppModule {}
老实说,我只是 运行 不知道哪里出了问题。解析器在我的上一个项目中工作得很好(但我没有使用 Mongoose,所以这可能是导致问题的原因)。下面是我的 .env 文件模板。
JWT_SECRET=
ENABLE_CORS=
PORT_BACKEND=
DATABASE_HOST=
DATABASE_PORT=
DATABASE_USER=
DATABASE_PWD
DATABASE_NAME=
CLIENT_HOST=
感谢所有花时间帮助我的人 ;)
您正在导入 env.ts
之前 ConfigModule 已导入并在您的 .env
文件中设置变量。
这就是调用 require('dotenv').config()
有效的原因。在幕后,这就是 ConfigModule 为您所做的。但是,您对 ConfigModule.forRoot
的调用发生在 在您导入 env.ts
之后 ,因此尚未导入 .env
文件并且那些变量没有尚不存在。
我强烈建议您查看 custom configuration files,它以“嵌套方式”为您处理此问题:
来自 Nest 文档,但请注意,您也可以使用已有的 env.ts
文件:
// env.ts
export default () => ({
// Add your own properties here however you'd like
port: parseInt(process.env.PORT, 10) || 3000,
database: {
host: process.env.DATABASE_HOST,
port: parseInt(process.env.DATABASE_PORT, 10) || 5432
}
});
然后将您的 AppModule 修改为以下内容。请注意,我们正在使用 forRootAsync 以便我们可以获得 ConfigService 的句柄并从中获取变量。
// app.module.ts
import configuration from './common/env';
@Module({
imports: [
ConfigModule.forRoot({
load: [configuration],
}),
//
MongooseModule.forRootAsync({
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => ({
uri: configService.get<string>('MONGO_URI'),
}),
inject: [ConfigService],
});
],
})
export class AppModule {}
作为替代方案,您也可以在顶部的 env.ts
文件中调用 require('dotenv').config()
,但您会错过所有 ConfigModule 助手,例如 dev/prod .env
个文件。
在我的例子中,我将@types/node 降级为与我的节点版本相同的版本。可能是一个提示。
在我的例子中只需要更换订单导入模块。
import { Module } from "@nestjs/common";
import { ConfigModule } from "@nestjs/config";
import { MongooseModule } from "@nestjs/mongoose";
import { AppController } from "./app.controller";
import { env } from "./common/env"; // call process.env.xxx here > undefined
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
}), // process.env.xxx must be called after this line
MongooseModule.forRoot(env.MONGO_URI),
],
controllers: [AppController],
})
export class AppModule {}
所以修复
import { Module } from "@nestjs/common";
import { ConfigModule } from "@nestjs/config";
// should place this at very first line
const envModule = ConfigModule.forRoot({
isGlobal: true,
})
import { MongooseModule } from "@nestjs/mongoose";
import { AppController } from "./app.controller";
import { env } from "./common/env";
@Module({
imports: [
envModule,
MongooseModule.forRoot(env.MONGO_URI),
],
controllers: [AppController],
})
export class AppModule {}
通过使用 JWT 模块的 registerAsync 并读取 process.env 内部的 useFactory 方法对我有用
@Module({
imports: [
JwtModule.registerAsync({
useFactory: () => ({
secret: process.env.JWT_SECRET_KEY,
signOptions: { expiresIn: 3600 },
}),
})
],
controllers: [AppController],
})