如何在package.json中设置环境变量?

597
如何在package.json中设置一些环境变量,以便与类似于npm start的命令一起使用?
这是我当前在package.json中拥有的内容:
{
  ...
  "scripts": {
    "help": "tagove help",
    "start": "tagove start"
  }
  ...
}

我想在启动脚本中设置环境变量(例如NODE_ENV),但仍希望能够使用单个命令npm start启动应用程序。


4
您可以阅读此答案 https://dev59.com/KWEh5IYBdhLWcg3whT3S#57509175 - Daniel Danielecki
22个回答

735

在脚本命令中设置环境变量:

...
"scripts": {
  "start": "node app.js",
  "test": "NODE_ENV=test mocha --reporter spec"
},
...

然后在您的应用程序中使用process.env.NODE_ENV

注意:此方法仅适用于Mac和Linux。有关Windows的信息,请参阅注释。


89
有人找到了Windows的替代品吗? - infinity
103
@infinity使用cross-env非常方便易用。 - mikekidder
179
@infinity 使用set NODE_ENV=test && mocha --reporter spec命令 - 测试和&&之间故意没有空格。 - Jamie Penney
33
"test": "NODE_ENV=test mocha --reporter spec" 无法在 Windows 系统上正常运行。 - Benny Code
25
env NODE_ENV=test mocha --reporter spec 会以本地跨平台的方式使用声明的环境变量,并且关键是它仅在 npm 脚本执行时被 ad hoc 和一次性地使用。(它不会被设置或导出供将来参考。)只要您从 npm 脚本运行命令,就没有问题。此外,在这种方式下,必须删除 "&&"。 - estaples
显示剩余17条评论

377

只需使用NPM包cross-env。非常简单。适用于Windows,Linux和所有环境。请注意,您不需要使用&&移动到下一个任务。您只需设置环境,然后启动下一个任务。感谢@mikekidder在此处的建议其中一条评论

来自文档:

{
  "scripts": {
    "build": "cross-env NODE_ENV=production OTHERFLAG=myValue webpack --config build/webpack.config.js"
  }
}

请注意,如果您想设置多个全局变量,只需连续声明它们,然后执行您的命令即可。
最终使用 spawn 执行的命令是:
webpack --config build/webpack.config.js

"

NODE_ENV 环境变量将由 cross-env 设置。

"

2
三个反斜杠可以用来转义所需的引号:"test": "cross-env TS_NODE_COMPILER_OPTIONS='{\\\"module\\\":\\\"commonjs\\\"}' mocha" - bvj
3
env 并非在所有平台上都能正常工作,因此需要使用 cross-env。直接使用 cross-env 即可解决问题。 - TetraDev
另外,也可以使用cross-env-shell代替cross-env。您可以在此处阅读有关它的信息:https://www.npmjs.com/package/cross-env#cross-env-vs-cross-env-shell - Nigrimmist
1
虽然对于“install”脚本不起作用,但我正在努力使用Playwright在运行playwright包的安装之前设置PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1。 - Eric Burel
根据@Teemuk的回答,这似乎更适用于安装:"preinstall": "export PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 || set PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1"。困难在于在安装过程中,您没有软件包,也不能有内联脚本,因此您必须找到一个纯shell解决方案,在preinstall命令中适用于Windows。 - Eric Burel
显示剩余2条评论

86

由于我经常需要使用多个环境变量,因此我发现将它们保存在一个单独的.env文件中很有用(请确保从源代码控制中忽略此文件)。然后(在Linux中)在启动应用程序之前,在您的脚本命令中添加export $(cat .env | xargs) &&

.env文件示例:

VAR1=value1
VAR2=value2
VAR3=value3
VAR_A=Hello World
VAR_B=format the .env file like this with new vars separated by a line break

示例 index.js:

console.log('Test', process.env.VAR_A, process.env.VAR_B);

示例 package.json 文件:

{
  ...
  "scripts": {
    "start": "node index.js",

    "env-linux": "export $(cat .env | xargs) && env",
    "start-linux": "export $(cat .env | xargs) && npm start",

    "env-windows": "(for /F \"tokens=*\" %i in (.env) do set %i)",
    "start-windows": "(for /F \"tokens=*\" %i in (.env) do set %i) && npm start",

  }
  ...
}

很不幸,我似乎无法通过从脚本中调用另一个脚本来设置环境变量——比如使用"start-windows": "npm run env-windows && npm start",所以这些脚本会有些冗余。

为了测试,您可以通过运行npm run env-linuxnpm run env-windows来查看环境变量,并通过运行npm run start-linuxnpm run start-windows测试它们是否进入了应用程序。


3
非常好,它幾乎為我完成了工作!我想添加一些評論:
  • 您的.env文件中不能有空行
  • 您的.env文件中的注釋將破壞您的腳本
  • 如果多個腳本使用相同的.env文件,則必須重複執行該操作
  • 我不得不刪除&&之前的空格才能使其正常工作
  • 如果您有多個.env文件,可能會更難維護
您的答案啟發了我準備這個建議: https://dev59.com/fF8f5IYBdhLWcg3wB-3E#61052350
- Felipe N Moura
我没有遵循env-windows脚本。cmd shell无法识别export和xargs。 - Derek Greer
感谢 @FelipeNMoura 和 @DerekGreer 的指正。我不确定为什么我认为 export $(cat .env | xargs) && set 在 Windows 上可以工作。我重新编写了 Windows 脚本,进行了测试,并对我的答案进行了编辑。 - Luke
使用 export $(cat .env | xargs)&& 代替 export $(cat .env | xargs) && 可以避免环境变量中出现额外的空格。这些空格在 console.log 中不会显示,但可能会破坏代码(就像我的一样)。 - Parth Sindhu
1
这应该是被接受的答案。 - LUser

82

我想为以后的Node探索者们贡献一点经验。在我的Ubuntu 14.04上,NODE_ENV=test无法使用,我必须使用export NODE_ENV=test,之后NODE_ENV=test也开始工作了,很奇怪。

对于Windows,正如已经说过的,你必须使用set NODE_ENV=test,但是为了跨平台的解决方案,cross-env库似乎行不通,而且你真的需要一个库来完成这个吗?

export NODE_ENV=test || set NODE_ENV=test&& yadda yadda

否则Windows将因无法识别的export NODE_ENV命令而崩溃,因此需要这些竖线。关于末尾空格,我不确定,但为了确保我也将其删除了。


8
你使用了 && 吗? NODE_ENV=test yadda 的意思是“在 yadda 的环境变量中设置 NODE_ENV 并运行 yadda”。NODE_ENV=test && yadda 的意思是“在本地环境中设置 NODE_ENV,但不导出它,然后运行 yadda”。NODE_ENV=test yadda 是首选方法。 - Josh Kelley
抱歉我有一段时间没有查看我的stackoverflow账户了。但基本上是由于愚蠢的Windows无法使用NODE_ENV=test && npm run test或类似的命令。我在我的testhelper.js文件中使用了更好的解决方案,即process.env["NODE_ENV"] = "testing"; - TeemuK
9
补充一下,当你使用 && 运行命令时,会丢失环境变量。在没有使用 export 导出的情况下设置环境变量,只对当前命令有效(也就是空命令)。如果要在不导出环境变量的情况下运行带有环境变量的命令,可以使用以下命令:NODE_ENV=test npm run test。最后,原因在于你现在已经将变量导出,在会话中可以使用它,而没有使用 export 导出时,你的 NODE_ENV 没有任何作用。 - Tarek
如果您想一次设置多个环境变量,请记住在cmd和bash中逻辑运算符严格从左到右,因此可以轻松实现链式操作。如果您想在Windows上执行这样的跨环境变量后获得干净的输出,可以像下面这样做:export NODE_ENV=0 2>nul || set NODE_ENV=0 && export TRIAL_MODE=1 2>nul || set TRIAL_MODE=1 && echo "$NODE_ENV $TRIAL_MODE %NODE_ENV %TRIAL_MODE"请记住,在Windows cmd中,环境变量在执行语句后可用,因此它们不适用于单行解决方案。 - Mateusz Budzisz

42

在Windows上尝试时,请将YOURENV替换为以下内容:

  {
    ...
     "scripts": {
       "help": "set NODE_ENV=YOURENV && tagove help",
       "start": "set NODE_ENV=YOURENV && tagove start"
     }
    ...
  }

27
我必须在“&&”之前去掉空格。 - Kenneth Solberg
3
@KennethSolberg的评论是让我成功的最后一步(仅适用于Windows)。 - ulu
2
我也遇到了空间问题。当记录字符串长度时,我可以看到空格被添加了。我尝试了转义引号 - 它们实际上存储在环境变量中。我尝试了其他分隔符,但都无济于事。删除空格或修剪值(这让我感觉不对),是解决此问题的唯一方法。 - Neil Gaetano Lindberg
空格!!!伙计,它真的起作用了! - Germa Vinsmoke
1
env-cmd 包可以自动获取 .env 文件。 - mercury
在Windows上,我必须使用单个&而不是双重&&,这对我很有效。例如:设置NODE_ENV = YOURENV&tagove帮助 - Vimal Bhatt

19

@luke的答案基本上是我需要的!谢谢。

鉴于被选答案非常简单明了(也是正确的),但已经有点过时了,我想提供一种从一个名为.env的文件中导入变量并在运行脚本时修复一些限制的替代方案。请尝试这个:

::: .env 文件 :::

# This way, you CAN use comments in your .env files
NODE_PATH="src/"

# You can also have extra/empty lines in it
SASS_PATH="node_modules:src/styles"

然后,在您的 package.json 文件中,您需要创建一个脚本来设置变量并在您需要这些脚本之前运行它:

::: package.json :::

scripts: {
  "set-env": "export $(cat .env | grep \"^[^#;]\" |xargs)",
  "storybook": "npm run set-env && start-storybook -s public"
}

一些观察:

  • 在grep'ed cat命令中的正则表达式将清除注释和空行。

  • &&不需要与npm run set-env“粘合”在一起,因为如果您在同一命令中设置变量,则需要它。

  • 如果您正在使用yarn,可能会看到警告,您可以将其更改为yarn set-env或者使用npm run set-env --scripts-prepend-node-path &&

不同的环境

使用它时的另一个优点是您可以拥有不同的环境变量。

scripts: {
  "set-env:production": "export $(cat .production.env | grep \"^[^#;]\" |xargs)",
  "set-env:development": "export $(cat .env | grep \"^[^#;]\" |xargs)",
}
请记得,当您的 .env 文件中含有密钥、密码或敏感/个人数据时,请勿将其添加到 git 仓库中!

export $(cat .env | grep \"^[^#;]\" |xargs) 命令只有在与我的主脚本相同的脚本中才能工作。这个可以:export $(cat .env | grep \"^[^#;]\" |xargs) && docker exec -it ${MY_VARIABLE}_wp sh。但这个不行:npm run set-env && docker exec -it ${MY_VARIABLE}_wp sh - Quentin D
我无法运行上面的grep命令,所以我使用了egrep。 export $(cat .env | egrep '^[^#]' | xargs) - Halil Kayer

17

更新:由于npm RFC 21,此解决方案可能会在 npm v7 中出现故障。

注意:不知道这是否适用于yarn


npm(和yarn)会将package.json中的许多数据作为环境变量传递给脚本。使用npm run env查看它们所有内容。这在https://docs.npmjs.com/misc/scripts#environment中有所记录,并且不仅适用于像prepublish这样的“生命周期”脚本,也适用于由npm run执行的任何脚本。

您可以在代码中访问这些环境变量(例如,在JS中使用process.env.npm_package_config_port),但它们已经可供运行脚本的shell访问,因此您还可以将其作为“scripts”中的$npm_...扩展访问(unix语法,在Windows上可能无效)。

"config"部分似乎就是为此而设计:

  "name": "myproject",
  ...
  "config": {
    "port": "8010"
  },
  "scripts": {
    "start": "node server.js $npm_package_config_port",
    "test": "wait-on http://localhost:$npm_package_config_port/ && node test.js http://localhost:$npm_package_config_port/"
  } 
这些“config”字段的重要特点是用户可以在不修改package.json文件的情况下覆盖它们
$ npm run start

> myproject@0.0.0 start /home/cben/mydir
> node server.js $npm_package_config_port

Serving on localhost:8010

$ npm config set myproject:port 8020
$ git diff package.json  # no change!
$ cat ~/.npmrc
myproject:port=8020

$ npm run start

> myproject@0.0.0 start /home/cben/mydir
> node server.js $npm_package_config_port

Serving on localhost:8020

请参考 npm configyarn config 文档。
看起来 yarn 读取了 ~/.npmrc,因此 npm config set 影响两者,但是 yarn config set 写入到 ~/.yarnrc,只有 yarn 才能看到它 :-(


4
请注意,自从NPM v7版本起,$npm_package_*变量不再自动放置在环境中,因此这可能会导致问题。 - Dan Dascalescu

17

如果你需要更大范围的环境变量或者想要重复使用它们,可以使用env-cmd

另外,.env文件也可以与direnv一起使用。

./.env 文件:

# This is a comment
ENV1=THANKS
ENV2=FOR ALL
ENV3=THE FISH

./package.json:

{
  "scripts": {
    "test": "env-cmd mocha -R spec"
  }
}

2
你如何在脚本中使用 ENV1? - ValRob
1
通常的 process.env.ENV1 - KARASZI István
但是,在 package.json 文件中吗?我读过似乎不可能(?) - ValRob
我不明白。你为什么要那样做? - KARASZI István
也许这是一个愚蠢的方法,但我已经更新了macOS Catalina,现在mongodb命令无法工作,所以我需要指定数据/文件夹mongod --dbpath ~/data/db。我想运行类似于npm mongodb的东西,它将获取环境变量dbpath并像往常一样运行mondodb...而且..我想与其他成员分享它。 - ValRob

14
当环境变量 NODE_ENV 被设置为 'production' 时,运行 npm install 命令时会完全忽略 package.json 文件中的 devDependencies。你也可以通过添加 --production 标志来强制实现此操作。
npm install --production

要设置NODE_ENV,您可以使用以下任何一种方法

方法1:为所有Node应用程序设置 NODE_ENV

Windows

set NODE_ENV=production

Linux、macOS或其他基于Unix的系统:

export NODE_ENV=production

这将为当前的bash会话设置NODE_ENV,因此在此语句之后启动的任何应用程序都将把NODE_ENV设置为production。

方法2:为当前应用程序设置NODE_ENV

NODE_ENV=production node app.js

这将只为当前应用程序设置NODE_ENV。当我们想在不同的环境下测试我们的应用程序时,这很有帮助。

方法3:创建.env文件并使用它

这使用了此处解释的思路。有关更详细说明,请参阅本文。

基本上,您需要创建一个.env文件,并运行一些bash脚本来在环境中设置它们。

为避免编写bash脚本,可以使用env-cmd软件包加载在.env文件中定义的环境变量。

env-cmd .env node app.js

第四种方法:使用cross-env包。

该包允许在所有平台上以一种方式设置环境变量。

使用npm安装后,只需将其添加到package.json中的部署脚本中,如下所示:

"build:deploy": "cross-env NODE_ENV=production webpack"

14

这将在Windows控制台中运行:

"scripts": {
  "setAndStart": "set TMP=test&& node index.js",
  "otherScriptCmd": "echo %TMP%"
}

npm run aaa

输出: test

有关详细信息,请参见此答案


7
应该这样写:set TMP=test && npm run bbb。在 && 前的空格也会被计算为 NODE_ENV 字符串的一部分。 - FisNaN
如果您将其用引号“”括起来,@FisNaN就不应该出现这种情况。 - kaiser
这段代码在&&前面没有空格。所以 "scripts": { "aaa": "set TMP=test && npm run bbb", "bbb": "echo %TMP%" } - O'Dane Brissett
@O'DaneBrissett 我现在无法检查,如果你确定它在Windows控制台中有效,请随意编辑答案。 - Serg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接