因为我们不希望项目代码中包含敏感数据,包括 package.json 文件,所以在我看来,使用环境变量是一个合理的选择。
示例 package.json:
"dependencies": {
"accounting": "~0.4.0",
"async": "~1.4.2",
"my-private-module":"git+https://${BB_USER}:${BB_PASS}@bitbucket.org/foo/bar.git"
这可能吗?
问题是不如果这是明智或不好,只是如果可能的话。
如果您使用
.env
文件,让我们使用 grep
或 eval
从 .env 文件中获取值环境变量。
按照@Paul的建议更新了
start2
:
"scripts": {
"start": "NODE_ENV=$(grep NODE_ENV .env | cut -d '=' -f2) some_script",
"start2": "eval $(grep '^NODE_ENV' .env) && some_script"
}
我有类似但不同的要求。对我来说,我想在脚本中使用环境变量。
我没有直接在 package.json 中使用环境变量,而是:
"some-script": "./scripts/some-script.sh",
在 some-script.sh 中:
#!/bin/sh
source .env
npm run some-other-script -- --prop=$SOME_ENV_VAR
以下是我如何设法解决
package.json
以达到相同目的。它使用一个脚本,从 package.json
的自定义部分读取 URL 模块,在其中插入环境变量,并使用 npm install --no-save
安装它们(--no-save
可以省略,具体取决于用例)。
作为奖励:它尝试从
.env.json
读取环境变量,该变量可以被 gitignore 忽略,并且对于开发非常有用。
package.json
env-dependencies.js
const execSync = require('child_process').execSync
const pkg = require('./package.json')
if (!pkg.envDependencies) {
return process.exit(0)
}
let env = Object.assign({}, process.env)
if (typeof pkg.envDependencies.localJSON === 'string') {
try {
Object.assign(env, require(pkg.envDependencies.localJSON))
} catch (err) {
console.log(`Could not read or parse pkg.envDependencies.localJSON. Processing with env only.`)
}
}
if (typeof pkg.envDependencies.urls === 'undefined') {
console.log(`pkg.envDependencies.urls not found or empty. Passing.`)
process.exit(0)
}
if (
!Array.isArray(pkg.envDependencies.urls) ||
!(pkg.envDependencies.urls.every(url => typeof url === 'string'))
) {
throw new Error(`pkg.envDependencies.urls should have a signature of String[]`)
}
const parsed = pkg.envDependencies.urls
.map(url => url.replace(/\${([0-9a-zA-Z_]*)}/g, (_, varName) => {
if (typeof env[varName] === 'string') {
return env[varName]
} else {
throw new Error(`Could not read env variable ${varName} in url ${url}`)
}
}))
.join(' ')
try {
execSync('npm install --no-save ' + parsed, { stdio: [0, 1, 2] })
process.exit(0)
} catch (err) {
throw new Error('Could not install pkg.envDependencies. Are you sure the remote URLs all have a package.json?')
}
将
"postinstall": "node env-dependencies.js"
添加到您的 package.json
,这样它将在每个 npm install
使用您想要的 URL 将您的私有 git 存储库添加到
package.json
(注意:它们的根目录都必须有 package.json
!):"envDependencies": {
"localJSON": "./.env.json",
"urls": [
"git+https://${GITHUB_PERSONAL_ACCESS_TOKEN}@github.com/user/repo#semver:^2.0.0"
]
},
(semver 说明符
#semver:^2.0.0
可以省略,但指的是 git 标签,这非常有用,因为它使您的 git 服务器成为一个成熟的包管理器)
npm install
不,这是不可能的。您应该使用
git+ssh
访问存储库,并将私钥存储在 ~/.ssh
中。
你的线条看起来像:
"my-private-module":"git+ssh://[email protected]/foo/bar.git"
不含任何敏感内容。
不,这是不可能的,因为 npm 不会将任何字符串值视为任何类型的模板。
最好只使用
git+ssh
(如果您的提供商支持)与 ssh 代理。
我有同样的需求,我的解决方案基于@Long Nguyen 的response。这样,我只能依赖 .env 文件中定义的内容。
.env
...
SKIP_PREFLIGHT_CHECK=true
...
package.json
...
"scripts": {
"test": "yarn cross-env $(grep SKIP_PREFLIGHT_CHECK ../../.env) react-app-rewired test --watchAll=false"
}
...
您可以使用环境值注入 package.json,如下所示:
任何以 npm_config_ 开头的环境变量都将被解释为配置参数。例如,将 npm_config_foo=bar 放入您的环境中会将 foo 配置参数设置为 bar。任何未指定值的环境配置都将指定 true 值。配置值不区分大小写,因此 NPM_CONFIG_FOO=bar 的作用相同。
您可以安装软件包https://www.npmjs.com/package/env-cmd 并且
.env
文件中的所有环境都将可见
即:
./.env:
ENV1=THANKS
ENV2=FOR ALL
ENV3=THE FISH
Package.json:
"scripts": {
"test": "env-cmd pact-broker can-i-deploy --broker-token=${ENV1}"
}
或您问题中的另一个例子:
"my-private-module":"env-cmd git+https://${BB_USER}:${BB_PASS}@bitbucket.org/foo/bar.git"
使用 Docker Compose 注入环境变量
app:
environment:
- NODE_ENV=staging
从 Dockerfile 运行 package.json 脚本
CMD [ "npm", "run", "start" ]
使用
echo
或 printenv
"scripts": {
"start": "node -r dotenv/config app.js dotenv_config_path=/run/secrets/$(echo $NODE_ENV)"
"start": "node -r dotenv/config app.js dotenv_config_path=/run/secrets/$(printenv NODE_ENV)"
}
不要将其用于敏感的环境变量。这是指向 Docker 机密文件的非常好的方法(如本示例所示)。
对于复杂的环境变量,可以使用 https://stedolan.github.io/jq/ 访问 JSON 文件(您的情况下的 env 文件) JSON 文件可能类似于
{
"env" :
{
"username" : "1345345",
"Groups" : [],
"arraytest" : [
{
"yes" : "1",
"no" : "0"
}
]
}
}
所以脚本可能是这样的来访问 yes 值
"scripts": {
"yes": "jq [].arraytest[0].yes?"
}
cross-var
用于跨平台目的):npm i cross-var dotenv-cli
.env
文件中),请在 $
中添加前缀为 package.json
的变量,如下所示:// .env
GOOGLE_API_KEY=mytoken
// package.json
"scripts": {
"my-script": "dotenv -- cross-var <your command> $GOOGLE_API_KEY"
}