今天,我试图找到一种方法来分隔模式(prod和dev)之间的全局变量。
我已经使用第三方模块“ dotenv”在“ process.env”中隐藏了敏感信息,但是无论我处于开发模式还是生产环境,在这里都可以找到适当的信息仍然很舒服。例如,如果我在本地工作,则使用本地或云测试数据库,而当我处于生产模式时,我想为真实数据库提供适当的凭据。因此,它会根据当前模式自动切换。
下面您可以看到到目前为止我提出的建议。对于结构问题或实践,经验,我将不胜感激。
先谢谢您!
server.js
import { environment } from "./environment";
import { apiExplorer } from "./graphql";
import express from "express";
import { ApolloServer } from "apollo-server-express";
import { database } from "./utils/database";
import { logger } from "./utils/logging";
import { verify } from "./utils/jwt";
database.connect();
apiExplorer.getSchema().then((schema) => {
// Configure express
const port = environment.port;
const app = express();
// Configure apollo
const apolloServer = new ApolloServer({
schema,
context: ({ req, res }) => {
const context = [];
// verify jwt token
context.authUser = verify(req, res);
return context;
},
formatError: (error) => {
logger.error(error);
return error;
},
debug: true
});
apolloServer.applyMiddleware({ app });
app.listen({ port }, () => {
logger.info(`?Server ready at http://localhost:${port}${apolloServer.graphqlPath}`);
});
})
.catch((err) => {
logger.error('Failed to load api', err);
})
数据库类
import mongoose from 'mongoose';
import { environment } from "../environment";
import { logger } from './logging';
class Database {
constructor() {
this._database = 'MongoDB';
this._username = environment.db.username;
this._password = environment.db.password;
this._dbName = environment.db.name;
}
connect() {
mongoose.Promise = global.Promise;
const url = `mongodb+srv://${this._username}:${this._password}@cocoondb-qx9lu.mongodb.net/${this._dbName}?retryWrites=true&w=majority`;
try {
mongoose.connect(url, { useNewUrlParser: true, useUnifiedTopology: true });
mongoose.connection.once('open', () => logger.info(`Connected to ${this._database}`));
mongoose.connection.on('error', err => logger.error(err));
} catch (e) {
logger.error(`Something went wrong trying to connect to the database: ${this._database}`)
}
}
}
export const database = new Database();
environment / index.js
import { development } from './develepment';
import { production } from './production';
import { merge } from "lodash"
const mode = process.env.NODE_ENV ? 'production' : 'development';
const values = process.env.NODE_ENV ? production : development;
export const environment = merge(values, { mode });
development.js
import dotenv from 'dotenv';
dotenv.config();
export const development = {
port: 8080,
db: {
username: process.env.DB_USER,
password: process.env.DB_PASSWORD,
name: process.env.DB_NAME
}
};
production.js
import dotenv from 'dotenv';
dotenv.config();
export const production = {
port: process.env.PORT,
newfromproduction: 'jkdl',
db: {
test: 'test'
}
};
file structure
src
-environment
- index.js
- development.js
- production.js
-graphql
-models
-utils
server.js
.babelrc
.env
.gitignore
package.json
答案 0 :(得分:0)
我认为您在正确的道路上。在我看来,抽象出特定于环境的配置是一种方法。
这里有几点要增强您的代码:
dotenv
中的merge
甚至是lodash
来确保您的应用程序代码在不受环境限制的情况下都可以运行。environment/index.js
导出的对象在所有环境中都应具有相同的形状,以避免仅在一个环境中发生的错误,而在您提供的摘录中不是这种情况。NODE_ENV
(或所需的任何单个环境变量名称),并确保在运行npm start
脚本时定义了该变量。这是我建议执行的代码(其中ALL_CAPS字符串应替换为在该环境中运行应用所需的实际值):
development.json
{
"port": 8080,
"db": {
"username": "DEVELOPMENT_USERNAME",
"password": "DEVELOPMENT_PASSWORD",
"name": "DEVELOPMENT_DATABASE_NAME"
},
"newfromproduction": ""
}
production.json
{
"port": 8080,
"db": {
"username": "PRODUCTION_USERNAME",
"password": "PRODUCTION_PASSWORD",
"name": "PRODUCTION_DATABASE_NAME"
},
"newfromproduction": "jkdl"
}
environment / index.js
import development from './development.json';
import production from './production.json';
const { NODE_ENV: mode } = process.env;
const configuration = {
development,
production
};
// using a little bit of destructuring magic but that is not necessary
export default { ...configuration[mode], mode };
package.json
"scripts": {
"start": "NODE_ENV=production node server",
"start:dev": "NODE_ENV=development nodemon server"
}
您可以将server.js
中的代码保持不变。
此方法有几个好处:
development.json
和production.json
,因此对于不需要知道密码是什么的开发人员来说,您的密码是安全的。如果开发人员需要配置文件才能在应用程序上工作,只需与他们共享development.json
的加密版本。这不是很理想,但是至少您的密码没有以纯文本格式存储在GitHub中。test
或stage
),则只需在environment
文件夹中创建JSON文件,并在{{1 }}(例如package.json
或"start:stage": "NODE_ENV=stage node server"
)。无需在"test": "NODE_ENV=test mocha"
中添加if
语句。一个小缺点:
environment/index.js
的值是非预期环境(例如NODE_ENV
)的字符串,则应用将崩溃,因为NODE_ENV=abc123
是configuration.abc123
,但是这不一定是一件坏事(拥有意外的环境不是一个好主意),并且您还可以改善我提供的用于处理这种情况的代码。