管理 NodeJS 配置标志的更好方法?
A better way to manage NodeJS configuration flags?
我有一个 NodeJS 应用程序,我需要为其提供各种标志以自定义环境。
我已经在使用 dotenv 处理环境文件,并且我也在从 CLI 将其预加载到应用程序:
"scripts": {
"hello": "DOTENV_CONFIG_PATH=/my/path/dev.env node --max_semi_space_size 64 --inspect=0.0.0.0 dist/index.js"
}
我的问题是:我开始遇到在某些情况下需要添加越来越多的 nodejs 标志的情况 - 有更好的方法吗?我无法想象将来将 20 个 cli args(即 --max_semi_space_size ...
传递给节点。
我 thought/heard 的一些选项是:
- 将脚本逻辑移动到外部文件
- 使用 node + flags 为 node 命令起别名
- 使用我的自定义设置重新编译节点
但这感觉很奇怪 - 我确信有一种方法可以处理不是那么棘手的问题。你会如何解决这个问题?我也在 docker,如果这对你的建议有任何影响的话。
ta!
最佳做法是创建一种可重用且可在多个级别上更改的机制。许多旨在广泛使用的 docker 容器都遵循这种方法。
分层配置
模块需要支持hierarchical configuration
。这意味着将有不止一种设置变量的方法,并且将有一个严格的层次结构,基于优先级,哪个值将是最终值。层次结构的最佳实践如下:
- 将值设置为默认值
- 检查配置文件中是否有新值,如果有则覆盖该值
- 检查环境变量是否有新值,如果有则覆盖该值
- 检查启动标志中是否有新值,如果有则覆盖该值。
此方法适用于 node CLI
参数,但层次结构较浅且在环境变量设置处停止。
经过这一系列检查后,您将获得变量的最终值。
应用程序配置变量
Node.js 有一个名为 nconf
的好库,您可以在 github 上找到它。该库允许您进行分层配置。这是一个简单的示例(取自库中的示例,针对 space 进行了修剪)
var nconf = require('nconf');
// 1. any overrides
nconf.overrides({
'always': 'be this value'
});
// 2. `process.env`
// 3. `process.argv`
nconf.env().argv();
// 4. Values in `config.json`
nconf.file('/path/to/config.json');
// 5. Any default values
nconf.defaults({
'if nothing else': 'use this value'
});
将其包装在您自己的模块中,并添加处理配置所需的额外逻辑
var myConfig = require('nconf');
..
...
..
module.exports = myConfig;
然后使用您代码中的配置,如下所示
var config = require('./myConfig');
config.get('hello');
这将允许您在映像中设置默认配置并在后续映像中覆盖它们。这是一个示例,第一个图像 base
将在构建期间从文件中设置 hello
标志,第二个图像将使用 ENV
覆盖设置:
FROM debian:latest as base
COPY ./hello_config.json /path/to/config.json
...
...
FROM base AS second
ENV hello="Hello world from second image!"
...
...
现在,当您创建容器时,您可以通过传递新的环境文件 (--env-file
) 或单个标志(-e
或 --env
)来覆盖更改
docker run --env hello="Hi from container!" --env-file ./new_conf.list secod
Note that the environment file should be in a shell format FLAG=VALUE and not in json format.
节点 CLI 参数
Node CLI 参数也可以用这种方法处理(唯一的区别是层次结构停止在 CLI 处)。容器应在 Dockerfile 中使用所需标志定义 NODE_OPTIONS
环境变量,如下所示:
...
ENV NODE_OPTIONS="--max_semi_space_size 64 --inspect=0.0.0.0"
...
这可以增强以接受构建选项以及逐渐构建变量
...
ARG NODE_OPTIONS=""
ENV NODE_OPTIONS="${NODE_OPTIONS} --max_semi_space_size 64"
ENV NODE_OPTIONS="${NODE_OPTIONS} --inspect=0.0.0.0"
...
现在,在构建过程中我们可以指定额外的选项如下
docker build --build-arg NODE_OPTIONS="--cpu-prof --heapsnapshot-near-heap-limit=3" .
与应用程序配置相同,您可以使用-env
或--env-file
文件来针对特定容器进行修改。
在我看来,package.json 文件应该尽可能干净。
通常对于这种情况,我会创建 scripts
或 shell
目录,然后将所有脚本放入单独的 bash 或 shell 文件中。最后只需从 npm 命令调用这些文件。
像这样:
我不确定在这种情况下使用 nconf
是个不错的选择..
我认为这可以满足您的需求:
https://nodejs.org/api/cli.html#cli_node_options_options
NODE_OPTIONS=options...
A space-separated list of command line options.
...
NODE_OPTIONS='--require "./a.js"' node --require "./b.js"
# is equivalent to:
node --require "./a.js" --require "./b.js"
...除了:
Node.js will exit with an error if an option that is not allowed in the environment is used
和 --max_semi_space_size
未在允许的选项中列出...但您可以尝试。
但无论如何
"scripts": {
"hello": "./run_node_with_options.sh"
}
# run_node_with_options.sh
DOTENV_CONFIG_PATH=/my/path/dev.env node --max_semi_space_size 64 --inspect=0.0.0.0 dist/index.js"
似乎是一个更可靠的解决方案。
我有一个 NodeJS 应用程序,我需要为其提供各种标志以自定义环境。
我已经在使用 dotenv 处理环境文件,并且我也在从 CLI 将其预加载到应用程序:
"scripts": {
"hello": "DOTENV_CONFIG_PATH=/my/path/dev.env node --max_semi_space_size 64 --inspect=0.0.0.0 dist/index.js"
}
我的问题是:我开始遇到在某些情况下需要添加越来越多的 nodejs 标志的情况 - 有更好的方法吗?我无法想象将来将 20 个 cli args(即 --max_semi_space_size ...
传递给节点。
我 thought/heard 的一些选项是:
- 将脚本逻辑移动到外部文件
- 使用 node + flags 为 node 命令起别名
- 使用我的自定义设置重新编译节点
但这感觉很奇怪 - 我确信有一种方法可以处理不是那么棘手的问题。你会如何解决这个问题?我也在 docker,如果这对你的建议有任何影响的话。
ta!
最佳做法是创建一种可重用且可在多个级别上更改的机制。许多旨在广泛使用的 docker 容器都遵循这种方法。
分层配置
模块需要支持hierarchical configuration
。这意味着将有不止一种设置变量的方法,并且将有一个严格的层次结构,基于优先级,哪个值将是最终值。层次结构的最佳实践如下:
- 将值设置为默认值
- 检查配置文件中是否有新值,如果有则覆盖该值
- 检查环境变量是否有新值,如果有则覆盖该值
- 检查启动标志中是否有新值,如果有则覆盖该值。
此方法适用于 node CLI
参数,但层次结构较浅且在环境变量设置处停止。
经过这一系列检查后,您将获得变量的最终值。
应用程序配置变量
Node.js 有一个名为 nconf
的好库,您可以在 github 上找到它。该库允许您进行分层配置。这是一个简单的示例(取自库中的示例,针对 space 进行了修剪)
var nconf = require('nconf');
// 1. any overrides
nconf.overrides({
'always': 'be this value'
});
// 2. `process.env`
// 3. `process.argv`
nconf.env().argv();
// 4. Values in `config.json`
nconf.file('/path/to/config.json');
// 5. Any default values
nconf.defaults({
'if nothing else': 'use this value'
});
将其包装在您自己的模块中,并添加处理配置所需的额外逻辑
var myConfig = require('nconf');
..
...
..
module.exports = myConfig;
然后使用您代码中的配置,如下所示
var config = require('./myConfig');
config.get('hello');
这将允许您在映像中设置默认配置并在后续映像中覆盖它们。这是一个示例,第一个图像 base
将在构建期间从文件中设置 hello
标志,第二个图像将使用 ENV
覆盖设置:
FROM debian:latest as base
COPY ./hello_config.json /path/to/config.json
...
...
FROM base AS second
ENV hello="Hello world from second image!"
...
...
现在,当您创建容器时,您可以通过传递新的环境文件 (--env-file
) 或单个标志(-e
或 --env
)来覆盖更改
docker run --env hello="Hi from container!" --env-file ./new_conf.list secod
Note that the environment file should be in a shell format FLAG=VALUE and not in json format.
节点 CLI 参数
Node CLI 参数也可以用这种方法处理(唯一的区别是层次结构停止在 CLI 处)。容器应在 Dockerfile 中使用所需标志定义 NODE_OPTIONS
环境变量,如下所示:
...
ENV NODE_OPTIONS="--max_semi_space_size 64 --inspect=0.0.0.0"
...
这可以增强以接受构建选项以及逐渐构建变量
...
ARG NODE_OPTIONS=""
ENV NODE_OPTIONS="${NODE_OPTIONS} --max_semi_space_size 64"
ENV NODE_OPTIONS="${NODE_OPTIONS} --inspect=0.0.0.0"
...
现在,在构建过程中我们可以指定额外的选项如下
docker build --build-arg NODE_OPTIONS="--cpu-prof --heapsnapshot-near-heap-limit=3" .
与应用程序配置相同,您可以使用-env
或--env-file
文件来针对特定容器进行修改。
在我看来,package.json 文件应该尽可能干净。
通常对于这种情况,我会创建 scripts
或 shell
目录,然后将所有脚本放入单独的 bash 或 shell 文件中。最后只需从 npm 命令调用这些文件。
像这样:
我不确定在这种情况下使用 nconf
是个不错的选择..
我认为这可以满足您的需求: https://nodejs.org/api/cli.html#cli_node_options_options
NODE_OPTIONS=options...
A space-separated list of command line options.
...
NODE_OPTIONS='--require "./a.js"' node --require "./b.js" # is equivalent to: node --require "./a.js" --require "./b.js"
...除了:
Node.js will exit with an error if an option that is not allowed in the environment is used
和 --max_semi_space_size
未在允许的选项中列出...但您可以尝试。
但无论如何
"scripts": {
"hello": "./run_node_with_options.sh"
}
# run_node_with_options.sh
DOTENV_CONFIG_PATH=/my/path/dev.env node --max_semi_space_size 64 --inspect=0.0.0.0 dist/index.js"
似乎是一个更可靠的解决方案。