8

您构建的 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或云服务器吗?这些都是要问自己的好问题。你在这里学到的方法是一个基础,可以与其他解决方案协同工作。我很快会在未来的文章中深入探讨这个问题,敬请期待。


Reco
4.6k 声望541 粉丝

敢作敢为