关于javascript:Nodejs无处不在的环境变量

1次阅读

共计 9064 个字符,预计需要花费 23 分钟才能阅读完成。

您构建的 Node.js 应用程序首先要在计算机上运行。您晓得,应用程序在任何须要运行的中央都能工作是很重要的。这可能是在你共事的电脑、公司外部服务器、云服务器或容器外部(可能应用 Docker)。输出 环境变量.

应用环境变量的说明性指南

环境变量是应用 Node.js 开发的一个根本局部,它容许您的应用程序依据您心愿它们运行的环境而体现出不同的行为。无论您的应用程序在哪里须要配置,您都能够应用环境变量。它们非常简单,而且十分丑陋!这篇文章将向您介绍如何创立和应用环境变量。

这篇文章将疏导您创立和应用环境变量,从而创立一个能够在任何中央运行的 Node.js 应用程序。


人们常常问我,我是如何决定什么是学习和投入工夫的,什么是放任自流的。对我来说,这是从这两个雷同的问题开始的(例如,问为什么和何时)。我敢打赌,你也会做相似的事件,不是吗?

为什么和什么时候?

当有人通知你某件事情很重要,你应该应用它时,我倡议问两个简略的问题。

  1. 为什么我应该应用它?
  2. 我应该在什么时候应用它(或不应用它)?

** 为什么?

当初是你问我为什么要应用环境变量的时候了。去吧;没关系。

如果您关怀使您的应用程序在任何计算机或云上运行(也就是您的环境),那么您应该应用它们。为什么?因为它们将您的应用程序的所有环境特定方面内部化,并放弃您的应用程序封装。当初,您能够通过批改环境变量在任何中央运行您的应用程序,而无需更改您的代码,也无需从新构建它!** 什么时候?

** 什么时候?

好了,当初你问我什么时候应该应用它们。简而言之,你的代码中任何会依据环境而扭转的中央。当你看到这些状况时,对任何你须要扭转或配置的中央都要应用环境变量。

上面是一些你应该思考应用环境变量的常见场景的具体例子。

  • 侦听哪个 HTTP 端口
  • 您的文件在什么门路和文件夹中,您想提供的服务

* 指向开发、暂存、测试或生产数据库。

其余的例子可能是服务器资源的 URL,测试与生产的 CDN,甚至是在 UI 中通过你的利用所处的环境来标记你的利用。

让咱们来探讨一下如何在 Node.js 代码中应用环境变量。

应用环境变量

您可能正在为 Express 服务器设置端口号。通常状况下,不同环境(例如;暂存、测试、生产)中的端口可能须要依据策略进行更改,并防止与其余应用程序发生冲突。作为开发人员,你不应该关怀这些,实际上,你也不须要关怀。上面是如何在代码中应用环境变量来抓取端口。

    // server.js
    const port = process.env.PORT
    console.log(`Your port is ${port}`);

试试这个。创立一个名为 “env-playground “ 的空文件夹。而后创立一个名为 server.js 的文件,并将下面的代码增加到其中。当初,当你执行 node server.js 时,你应该看到一条音讯说 “Your port is undefined”。

你的环境变量不在那里,因为咱们须要把它们传递进来。让咱们思考一些能够解决这个问题的办法。

1. 应用命令行

  1. 应用 .env 文件。

命令行

将 port 传入您的代码的最简略办法是在命令行中应用它。在命令行中指定变量的名称,前面是等号,而后是值。而后调用您的 Node.js 应用程序。

PORT=8626 node server.js

你会看到端口显示在这样的音讯中:” 你的端口是 8626″。

_这个 8626 是什么货色?为什么不是 4200 或者 3000 或者更传统的端口?好吧,我是迪斯尼的忠诚粉丝,有一个叫史迪奇的角色也被称为试验 626._。

你能够反复这个模式,也能够增加其余变量。上面是一个传递两个环境变量的例子。

    PORT=8626 NODE_ENV=development node server.js。

依照环境变量名后加等号再加值的模式。这很容易做到,但也太容易犯输出谬误了。这就有了下一个选项。

缩小.env 文件的凌乱

一旦你定义了其中的几个,你脑海中的下一个念头可能就是如何治理它们,使它们不会成为保护的噩梦。设想一下,数据库连贯、端口和密钥都有好几个。当你把它们都打在一条线上时,这并不能很好地扩大。而且可能会有私人信息,如密钥、用户名、明码和其余机密。

从命令行运行它们当然很不便。但它也有它的毛病。

  1. 没有一个很好的中央能够看到变量列表。

2. 从命令行打字太容易出错了。
3. 要记住所有的变量和它们的值并不现实。
4. 即便应用 npm 脚本,你依然必须放弃它们的最新性。

对于如何组织和保护环境变量,一个风行的解决方案是应用 .env 文件。我真的很喜爱这种技术,因为它使我能够在一个中央疾速读取和批改它们变得超级容易。

在你的应用程序的根目录下创立 .env 文件,并将你的变量和值增加到其中。

    NODE_ENV=development
    PORT=8626
    _# 在这里设置你的数据库 /API 连贯信息。_API_KEY=**************************
    API_URL=**************************

记住你的.gitignore 文件

.env文件是一个很好的办法,能够在一个中央看到所有的环境变量。只有确保不要把它们放到源代码管制中。否则,你的历史记录将蕴含对你的机密的援用。

创立一个 .gitignore 文件(或者编辑现有的文件,如果你曾经有了),并增加 .env 到其中,如下图所示。.gitignore文件会通知源管制疏忽你列出的文件(或文件模式)。

小心将.env 增加到.gitignore 文件中,并在增加你的_ .env_之前提交该更改。否则,你就有可能将你的.env_的晚期版本提交到源代码管制中。

您能够通过应用 Visual Studio Code (VS Code)中的命令调色板将一个文件增加到您的 .gitignore 文件中。依照以下步骤进行。

  1. 在 VS Code 中关上你要增加到 .gitignore 的文件。
    在 Mac 上用 CMD+SHIFT+P 关上命令调色板,在 Windows 上用 CTRL+SHIFT+P 关上。
  2. 输出 “ 疏忽 ”。
  3. 抉择 “Git: 从菜单中增加文件到.gitignore

这将把你以后关上的文件名增加到 .gitignore 文件中。如果你没有创立 .gitignore 文件,它将为你创立!

将.env 退出到.gitignore 中。

您的.env 文件的语法高亮

如果你应用 VS Code,你会想要增加 dotenv 扩大。这将为你的 .env 文件的内容提供语法高亮,并使你更容易应用 .env 文件中的变量。

上面是装置了 dotenv 扩大的 VS Code 中的文件。

.env 文件在 VS Code 中具备语法高亮性能。

读取.env 文件

当初你可能在想,有些货色必须寻找 .env 文件,你是对的!你能够本人写代码来寻找文件,解析,并将它们读到你的 Node.js 利用中。

你能够写你本人的代码来找到这个文件,解析它,而后把它们读到你的 Node.js 利用中。或者你也能够通过 npm 找到一种不便的办法,将变量一次性读到你的 Node.js 利用中。你很可能会遇到 npm 上的 dotenv 包,它是我的最爱,也是我举荐你应用的。你能够像这样 npm install dotenv 来装置它。

而后你能够在你的我的项目中要求应用这个包,并应用它的 config 函数 (config 也有一个 load 的别名,以防你在野外看到) 来寻找 .env 文件,读取你定义的变量,并将它们提供给你的应用程序。

依照以下步骤进行。

  1. 创立一个 package.json 文件

2. 装置 dotenv 的 npm 包。
3. 写代码读取.env
4. 运行代码

创立一个 package.json 文件

你须要一个 package.json 文件来配置你的版本,跟踪你的依赖关系,并蕴含你的 npm 脚本。通过运行以下命令来实现

npm init -y

这将创立一个 “package.json “ 文件,其中蕴含根本设置。

从 npm 装置 dotenv

你须要读取 .env 文件,而 npm 上的 dotenv 包能够很好地实现这个工作。运行以下命令装置 dotenv 包

npm install dotenv

这将把 dotenv 包和它的文件增加到你的 node_modules 文件夹中,并在 package.json 文件中为 dotenv 创立一个条目。

读取.env 文件

是时候用一点代码读取 .env 文件了。用上面的代码替换你的 server.js 文件的内容。

// 服务器.js
console.log(Your port is ${process.env.PORT}); _// undefined
_const dotenv = require(‘dotenv’);
dotenv.config();
console.log(Your port is ${process.env.PORT}); _// 8626_。

该代码显示了 PORT 环境变量的初始值,该变量将是未定义的。而后,它须要 dotenv 软件包,并执行其 config 函数,读取 .env 文件并设置环境变量。最初一行代码显示 “PORT “ 为 8626。

运行代码

当初,应用以下命令,在不传递端口的状况下,在命令行中运行代码

node server.js

请留神控制台日志信息显示端口最后是未定义的,起初变成了 8626。dotenv 软件包读取并设置这些值,实际上是为您做了恶浊的工作。

轻松找到您的变量

当初,咱们有了一个在 .env 文件中创立变量的繁多中央,咱们可能会思考如何在 Node.js 代码中轻松检索所有这些变量。为什么要这样做?这个问题问得好! 好吧,你能够在代码中应用以下语法来援用变量。

process.env.YOUR_ENV_VAR_GOES_HERE

然而,你是否想在你须要的中央都这样做(你可能在多个中央须要它们)?还是应该把咱们所有的环境变量收集在一个中央? 当然是后者! 为什么这么说呢? 如果你真的在所有须要的中央都援用变量,可能会比在一个中央援用变量更难重构和保护。

我倡议创立一个模块,负责收集环境变量。这样能够很容易地一次性看到它们,并将它们映射到可读的名称上。

这里有两个不错的抉择能够思考。

  1. 在一个模块中手动设置和导出它们。

2. 应用一个库来读取并在一个模块中导出它们。

这两种技术都波及创立一个模块,但它们在环境变量的映射和裸露形式上有所不同。让咱们认真看看这两种技术,并衡量一下它们的区别。

手动组织

创立一个模块(上面的例子显示的是config.js),在这个模块中,你能够收集变量,将它们映射为名称明确且可读的属性,并将它们导出。

让咱们在一个名为 config.js 的文件中创立一个新模块。而后将以下代码复制并粘贴到文件中。

    // config.js
    _const_ dotenv = require('dotenv');
    dotenv.config();
    module.exports = {
      endpoint: process.env.API_URL,
      masterKey: process.env.API_KEY,
      port: process.env.PORT
    };

这个例子展现了咱们如何将环境变量整合到一个文件中。

让咱们再次批改 server.js,这次是导入 config.js 模块并应用它来拜访咱们的环境变量。用上面的代码替换server.js 的内容。

    // server.js
    _const_ {port} = require('./config');
    console.log(`Your port is ${port}`); _// 8626_

应用 node server.js 运行代码,你会看到 “ 你的端口是 8626 “ 的音讯。环境变量正在被 config.js 文件中的 dotenv 代码读取。你的 server.js 文件导入 config.js 中的模块并提取端口变量。

你能够把 config.js 文件导入到你须要的中央,而后用 destructuring 来提取你须要的货色。你只调出了 port,但你当然能够调出模块中导出的任何一个值。

    const {endpoint, masterKey, port} = require(‘./config’);

这个技术有什么价值?

1. 它很容易
2. 明确所有环境变量的映射形式。
3. 你能够将变量重命名为更易读的属性。
4. 你能够从非环境变量中增加其余配置属性。

这里的关键点是,config 模块的目标变成了收集和裸露所有的配置,不论它来自哪里。

应用库进行整顿

手动技术的一个结果是,当你增加一个新的环境变量时,你必须把它增加到 config 模块中。例如,如果你须要制作一个新的变量,你须要进入这个配置模块,并增加这样的内容。

    visionApiUrl=process.env.VISION_API_URL

我不介意这个结果,因为无论如何我都要通过我的代码来应用新的值。但我指出这一点是因为有一种办法能够主动收集它们。

dotenv npm 包中的 dotenv.config() 函数会读取 .env 文件,将变量调配给process.env,而后返回一个蕴含内容的对象(命名为parsed),如果失败的话,它还会抛出一个谬误。

上面的代码读取 .env 文件,并收集 envs 对象中的变量。

    // config.js 
    _const_ dotenv = require('dotenv');
    _const_ result = dotenv.config();
    _if_ (result.error) {_throw_ result.error;}
    _const_ {parsed: envs} = result;
    console.log(envs);
    module.exports = envs;

而后,你能够从一个模块中导出这个对象,并再次在你的应用程序中轻松拜访它。你拜访变量的代码可能是这样的

    const {endpoint, masterKey, port} = require(‘./config’);

你应该用哪个计划?这由你本人决定。但请思考是否要将 npm 包 dotenv 作为运行时依赖。兴许在更高的环境(比方生产环境)中,还有其余的办法来获取环境变量,在这些环境中,平安是最重要的。你甚至心愿你的 node 利用中的代码可能读取如此重要的文件吗?你可能会感觉很酷,但如果有一种办法能够读取变量,并在你的 package.json 文件中把 dotenv 包变成一个 devDependency 呢?

我倡议你应用第一种技术,即在模块中手动设置环境变量,比方config.js。这容许你删除 dotenv 作为运行时的依赖 – 假如你还做了一件事:预加载环境变量。这也容许你缩小你的运行时依赖性。

缩小您的依赖性

你有很多对 npm 包的依赖。当你打算你的应用程序的生命周期和保护时,每一个都是你应该思考的。你可能曾经在思考如何将你的依赖性缩小到最低限度。我也是这样做的。

dotenv 包是很棒的,但咱们不须要它成为运行时的依赖。dotenv 包提供了一个选项,你能够在你的代码之外预加载变量。你能够加载变量,并从咱们的代码中删除读取 .env 文件的代码。更少的代码就是更少的行数,可能会中断或被保护。

还不释怀吗?您是否思考过如何在云中拜访这些环境变量?你心愿你的代码试图读取一个文件吗?我对此投了一个嘹亮的 “ 不 ”。我更心愿我的代码不要试图读取文件,因为如果我把它带到云端,我心愿这些解决方案甚至没有 .env 文件。

如何从咱们的代码中删除 dotenv 的运行时依赖,但又不失去曾经取得的价值?首先,在装置 dotenv npm 包的时候,你能够像这样把它保留为开发依赖关系。

    npm install dotenv --save-dev。

而后删除所有在 dotenv 上应用 require 的代码,包含本文之前提到的 dotenv.config() 代码。这包含本文后面提到的 dotenv.config() 代码。

当初的问题是,你之前是依附 dotenv 来加载环境变量的。这就是预加载选项发挥作用的中央。

你能够应用- require (-r ) 命令行选项来预加载 dotenv 来运行你的 node 利用。上面的命令将应用 dotenv 从文件.env 中预载所有环境变量,并使它们在你的应用程序中可用。所以你当初曾经从你的代码中删除了所有对 dotenv 的援用。

    node -r dotenv/config server.js

当你想让你的利用运行在文件不存在(兴许不应该存在)的中央时,这很有用,比方在运行中的 docker 容器或云服务器中。能够从 node - h 内看到 - r 选项的阐明:

    -r, --require=...                   module to preload (option can be repeated)

Leveraging npm Scripts

我强烈建议把你的命令放到一个 npm 脚本中。这使得它更容易运行,而不是输出所有这些标记。兴许你能够为它创立一个自定义脚本或者应用 npm 启动脚本。上面是你应用自定义脚本时脚本的样子。

    scripts: {"start_local": "node -r dotenv/config server.js"}

命令 npm run start_local 就会启动这个命令。当然,你能够随便命名这个脚本。

为什么不应用 npm start?问得好,你当然能够这样做。你当然能够这样做。我喜爱把npm start 保留给我在没有 docker 容器的状况下如何在生产中运行它,这可能只是像这样。

    scripts: {"start": "node server.js"}

这里的要害是,无论应用哪种 npm 脚本,你都在运行完全相同的 node 代码!区别在于你的变量如何设置。区别在于如何设置你的变量。你当初曾经从你的应用程序中形象出了你的配置。

好的 npm 工具

如何记住所有的 npm 脚本?这很简略 – 你不须要!我依附平凡的工具来帮忙运行我的 npm 脚本。尽管我喜爱伪装我晓得所有的脚本名称和它们的具体作用,但事实上,我更心愿有一个工具能够显示出列表,我能够抉择它。

在我抉择的代码编辑器中,有两个很棒的工具能够做到这一点。VS Code。

1.npm 的脚本纲要

  1. npm 扩大

npm 脚本纲要是内置在 VS Code 中的,并显示在资源管理器视图中。请留神上面的截图显示了我的 package.json 文件中的 npm 脚本,如果你在你的我的项目中没有看到这个,请确保将 npm.enableScriptExplorer 设置为 true。如果你在你的我的项目中没有看到这个,请确保在 VS Code 的 settings.json 中把 npm.enableScriptExplorer 设置为 true。

你能够右键点击一个 npm 脚本,而后关上、运行或调试它。

如果你像我一样喜爱用手敲键盘,那么你可能更喜爱 VS Code 的 npm 扩大。在装置了 VS Code 的 npm 扩大之后,你就能够在命令板上运行 npm 脚本了,在 Mac 上只有输出 CMD+SHIFT+P 就能够了。

只有在 Mac 上输出CMD+SHIFT+P,或者在 Windows 上输出CTRL+SHIFT+P。而后开始输出npm,抉择 “npm: 运行脚本 ”,如下图所示。

而后你会看到一个 npm 脚本的列表。从这里开始,你能够开始输出你想要的脚本的名字,直到你想要的脚本被高亮显示。或者你应用箭头抉择你想要的脚本。而后按 “ENTER “ 来运行它。

我喜爱这样,因为它让我的手放在键盘上,这感觉比在鼠标 / 触控板和键盘之间切换更有效率。

给一个这样的尝试。

无论在哪里运行,你的代码都是一样的。

你的应用程序没有意识到环境变量的起源。您运行它的形式,即预加载,是在您的本地机器上提供它们。

让咱们进一步探讨为什么你可能心愿你的应用程序对其配置没有意识。

Docker 容器

设想一下,咱们正在一个 Docker 容器中运行。容器的传统领导说,容器内的利用不应该晓得它们的配置。这样一来,只有容器和运行容器的任何货色就必须提供哪些变量达成协议,容器就能够在任何中央运行。

在云端运行的

当你把咱们的利用带到云端时,各种云提供商也都有方法让你设置环境变量。因而,再次强调,如果应用程序仅仅应用变量,而运行它的货色(在这种状况下,云提供商的服务)为您提供了定义这些变量的办法,您就能够了。

  • 你的应用程序与其配置的这种拆散,很大水平上来自于被称为 12 因素的领导。如果你还没有浏览过这方面的内容,请在这里理解更多_ https://12factor.net__。

与您的团队分享

你的队友如何晓得要为你的利用创立哪些环境变量?他们应该在你的代码中搜寻这些变量吗?他们应该打电话问你吗?当然不是,你没有工夫亲自去访问每一个开发者!

当你的 .env 文件没有被推送到源码管制中时(这是不应该的),重要的是要让大家分明这个文件的形态应该是什么样的。我举荐的技术是创立一个名为 .env.example 的文件,其中蕴含变量,但应用假值。这个文件可能看起来像上面的模板。

.env.example

NODE_ENV= 开发
PORT=8626
# 在这里设置你的数据库连贯信息 API_KEY=your-core-api-key-goes-here

你的团队能够把这个文件的内容复制到他们本人的.env 文件中,而后输出他们须要的值。在示例文件中列出非秘密的值是齐全失常的。留神到.env.example 文件中的 PORTNODE_ENV都被设置了,但 API_KEY 没有被设置。明智地抉择你推送到源代码管制的内容。

而后,你能够在你的 README.md 中援用这个文件,你的队友能够很快学会如何设置本人的值。问题解决了。

环境变量的作用

这只是对如何应用环境变量以及一些能够应用环境变量的神奇工具的一瞥。总的来说,我倡议你应用环境变量,并遵循以下步骤。

  1. 创立一个 .env 文件

2. 在你的 .gitignore 文件中疏忽它。
3. 应用 VS Code 来编辑你的 .env 文件。
4. 装置 VS Code 的 dotenv 扩大
5. 装置 VS Code 的 npm 扩大
6. 读取 dotenv npm 包中的.env 文件作为开发依赖。
7. 应用 dotenv 的预加载选项来删除对它的任何运行时援用。
8. 应用 npm 脚本来运行你的 node 利用。
9. 为你的变量创立一个名为 .env.example 的模板文件。

如果你喜爱我应用的字体和主题,它们是 Dank Mono 和 Winter is Coming (Blue)。你能够找到 这里的 Dank Mono 字体 并装置 这里的 Winter is Coming 主题_。我最初一次查看时,字体的价格是 40 英镑,而主题是收费的_。

然而等一下,你想让你的服务器有一个收费的字体吗?你心愿你的服务器有一个 .env 文件吗?你应用 Docker 或云服务器吗?这些都是要问本人的好问题。你在这里学到的办法是一个根底,能够与其余解决方案协同工作。我很快会在将来的文章中深入探讨这个问题,敬请期待。

正文完
 0