这是来自 Mozilla 身份团队的Node.JS 假日季系列的第 7 集,共 12 集。今天我们将讨论配置。
在本期“Node.JS 假日季”系列中,我们将介绍node-convict
,它是一个帮助管理 node.js 应用程序配置的工具。它提供透明的默认值和内置类型,使错误更容易发现和调试。
问题
关于应用程序配置,有两个主要问题
- 大多数应用程序至少会有几个不同的部署环境,每个环境都有自己的配置需求。
- 在源代码中包含凭据和敏感信息可能存在问题。
这些问题可以通过根据环境初始化某些设置,并使用环境变量来存放更敏感的设置来解决。node.js 开发者常用的模式是创建一个导出配置的模块,例如
var conf = {
// the application environment
// "production", "development", or "test
env: process.env.NODE_ENV || "development",
// the IP address to bind
ip: process.env.IP_ADDRESS || "127.0.0.1",
// the port to bind
port: process.env.PORT || 0,
// database settings
database: {
host: process.env.DB_HOST || "localhost:8091"
}
};
module.exports = conf;
这已经足够好了,但仍然有一些其他问题
- 如果某个设置配置错误怎么办?我们可以通过尽早检测和报告错误配置来节省麻烦。
- 运维/测试/和其他可能需要调整设置或诊断问题的协作者是否能轻松理解它?更具声明性的格式,同时包含文档,可以使生活更轻松。
登场 convict
Convict 通过引入配置模式来解决这些其他问题,您可以在其中为每个设置设置类型信息、默认值、环境变量和文档。
使用 convict,上面的示例变为
var convict = require('convict');
var conf = convict({
env: {
doc: "The applicaton environment.",
format: ["production", "development", "test"],
default: "development",
env: "NODE_ENV"
},
ip: {
doc: "The IP address to bind.",
format: "ipaddress",
default: "127.0.0.1",
env: "IP_ADDRESS"
},
port: {
doc: "The port to bind.",
format: "port",
default: 0,
env: "PORT"
},
database: {
host: {
default: "localhost:8091",
env: "DB_HOST"
}
}
});
conf.validate();
module.exports = conf;
信息大体相同,但编码在模式中。由于所有信息都编码在模式中,我们可以导出它并以更易读的格式显示它,并且可以使用它进行验证。这种声明式方法是 convict 更健壮和更易于协作的原因。
模式中包含什么
您会注意到每个设置有四个可能的属性——每个属性都有助于我们实现更健壮和更易于理解的配置。
- 类型信息:
format
属性指定内置 convict 格式(ipaddress
、port
、int
等),或者可以是一个函数来检查自定义格式。在验证期间,如果格式检查失败,它将被添加到错误报告中。 - 默认值:每个设置必须具有默认值。
- 环境变量:如果
env
指定的变量有值,它将覆盖设置的默认值。 - 文档:
doc
属性非常直观。将其放在模式中而不是注释中的好处是,我们可以调用conf.toSchemaString()
并将其显示在输出中。
分层添加配置
默认值的集合成为一个基础配置,您可以在其上叠加额外的配置,使用conf.load
和conf.loadFile
。例如,您可以根据条件叠加一个包含特定环境设置的 JavaScript 对象
var conf = convict({
// snip ... assume the same schema as above
});
if (conf.get('env') === 'production') {
// use the production port and database host
conf.load({
port: 8080,
database: {
host: "ec2-117-21-174-242.compute-1.amazonaws.com:8091"
}
});
}
conf.validate();
module.exports = conf;
或者,如果您为每个环境创建单独的配置文件,您可以简单地使用loadFile
来叠加它们
conf.loadFile('./config/' + conf.get('env') + '.json');
loadFile
还可以通过传入一个数组来一次加载多个文件
// CONFIG_FILES=/path/to/production.json,/path/to/secrets.json,/path/to/sitespecific.json
conf.loadFile(process.env.CONFIG_FILES.split(','));
使用load
和loadFile
分层配置非常有用,如果您有特定环境的公共设置,这些设置不需要在环境变量中设置。拥有单独的、声明性的 JSON 配置可以提高对哪些设置应该在环境之间改变的可见性。这些文件使用cjson加载,因此它们可以包含任意数量的注释以供进一步说明。
还要注意,环境变量始终优先,即使在使用load
或loadFile
加载设置之后也是如此。要查看当前设置是什么样,您可以使用conf.toString()
将整个内容序列化。
V 代表验证
设置组合好后,您可以执行验证,以检查每个设置的值是否符合模式中定义的正确格式。Convict 提供了一些内置格式,例如"url"
、"ports"
和"ipaddress"
等,您也可以使用 JavaScript 的全局构造函数(例如Number
)来指定类型。如果您完全省略了format
属性,convict 将检查设置是否与默认值具有相同的类型(根据Object.prototype.toString.call
)。例如,以下三个模式是等效的
var conf1 = convict({
name: {
format: String
default: 'Brendan'
}
});
// with no format specified, convict will assume it's the type
// of the default value
var conf2 = convict({
name: {
default: 'Brendan'
}
});
// a more succinct version
var conf3 = convict({
name: 'Brendan'
});
此外,还有一个枚举式格式,如示例中所示,您可以在其中指定一组明确的允许值,例如["production", "development", "test"]
。列表中不存在的任何值都会导致验证失败。
除了内置类型之外,您还可以提供自己的格式检查函数。例如,此模式中的格式函数检查设置是否为 64 个字符的十六进制字符串
var check = require('validator').check;
var conf = convict({
key: {
doc: "API key",
format: function (val) {
check(val, 'should be a 64 character hex key').regex(/^[a-fA-F0-9]{64}$/);
},
default: '3cec609c9bc601c047af917a544645c50caf8cd606806b4e0a23312441014deb'
}
});
调用conf.validate()
将在任何验证失败的设置上抛出一个错误,其中包含有关每个设置的详细信息。这对避免在每次配置错误后重新部署非常重要。使用自定义键格式示例中的配置,下面是错误的外观
conf.set('key', 'foo');
conf.validate();
// Error: key: should be a 64 character hex key: value was "foo"
总结
Convict 以一种更健壮、更易于协作者访问的方式扩展了配置 node.js 应用程序的标准模式,这些协作者可能不太愿意深入研究命令式代码以检查或修改设置。使用配置模式,我们可以为项目协作者提供有关每个设置的更多上下文,并提供配置错误时的验证和早期错误。
系列中的先前文章
这是一个包含 12 篇关于 Node.js 的文章的系列中的第七部分。之前的文章是
- 追踪 Node.js 中的内存泄漏
- 完全加载的 Node
- 使用安全的客户端会话构建简单且可扩展的 Node.JS 应用程序
- 出色的前端性能 第 1 部分 - 合并、压缩和缓存
- 构建一个不会熔化的 Node.JS 服务器
- 出色的前端性能,第 2 部分:使用 etagify 缓存动态内容
关于 Robert Nyman [荣誉编辑]
Mozilla Hacks 的技术布道师和编辑。发表关于 HTML5、JavaScript 和开放网络的演讲和博客文章。Robert 是 HTML5 和开放网络的坚定支持者,自 1999 年以来一直在从事网络前端开发工作——在瑞典和纽约市。他还经常在http://robertnyman.com上发表博客文章,喜欢旅行和结识新朋友。
2 条评论