初识dotenv

1,758 阅读6分钟

dotenv

前言

为什么要去讲一下dotenv,甚至为它去开一个专栏呢,最初是因为我的指导老师鼓励我探究 dotenv 的源码,并向班上的同学分享所学。尽管 dotenv 是 npm 中常用的模块之一,但是我在掘金上,还是其他技术知识分享平台上看到的关于dotenv的文章,对于dotenv的源码解析都是比较少的,大多数都是讲解一下它的基础原理(现在dotenv对外导出的方法愈发丰富了),但是dotenv源码对于很多小伙伴来说是值得去考究,也是比较容易去考究的!

如此年轻的我们,就是要有打破砂锅问到底的精神,所以接下来我会从外到里向大家去讲解dotenv!

与君共勉!

dotenv是什么

Dotenv 是一个零依赖的 Node.js 模块,主要用于简化环境变量配置的过程。

零依赖的 Node.js 模块是指在使用过程中不依赖其他第三方模块或库的情况下,能够独立运行和完成其功能的模块。换句话说,它们不需要依赖于其他模块或库来提供所需的功能或实现。这种类型的模块通常具有较小的体积,且更容易管理和维护。

Dotenv 是一个轻量级的工具,它不依赖于任何其他库或模块,这意味着你可以很容易地将其添加到任何项目中而不需要担心额外的依赖关系。

dotenv的作用

那么在项目为什么要去使用dotenv模块呢(它可以完成什么样的功能)?

加载环境变量

Dotenv 的主要功能是读取 .env 文件中的键值对(文件中的数据),并将它们作为环境变量加载到 process.env 对象中。这样,你的应用程序就可以通过 process.env 来访问这些变量。

分离配置和代码

Dotenv 支持一种最佳实践,即将配置与代码分离。这是十二要素应用程序方法论中的一项重要原则。十二要素应用程序方法论是由 Heroku 联合创始人 Adam Wiggins 提出的,用于构建可扩展、易维护的现代应用程序。

The Twelve-Factor App (简体中文) (12factor.net)

优点

  • 安全:敏感信息(如密码、密钥等)保存在 .env 文件中,而不是代码库中,减少了敏感数据泄漏的风险。

  • 易于管理配置:将配置数据从代码中分离出来,使代码更易于维护和管理。开发人员可以专注于业务逻辑,而不必担心配置问题。

  • 易于切换:.env 文件提供了一种集中管理环境变量的方法,可以在开发、测试和生产环境中使用不同的配置文件,方便地切换环境配置。

如何使用dotenv

1.安装 dotenv 模块:首先,你需要在你的 Node.js 项目中安装 dotenv 模块。你可以使用 npm 或 yarn 进行安装,具体命令如下:

npm install dotenv

或者

yarn add dotenv

2.创建 .env 文件:在你的项目根目录下创建一个名为 .env 的文件。在这个文件中,你可以定义你的环境变量及其对应的值。例如:

PORT=3000
DB_HOST=localhost
DB_USER=root
DB_PASSWORD=secret

这些变量名和值之间使用等号进行分隔。

3.在应用程序中加载 dotenv:在你的应用程序的入口文件(如 index.jsapp.js)中,通过引入 dotenv 模块调用config方法来加载 .env 文件中定义的环境变量。

通常,这一步会放在应用程序的最顶部,以确保环境变量在应用程序的任何其他地方都可用。

require('dotenv').config();

4.访问环境变量:一旦加载了 dotenv 模块,你就可以在应用程序的任何地方访问 .env 文件中定义的环境变量了。例如:

const port = process.env.PORT;
const dbHost = process.env.DB_HOST;
const dbUser = process.env.DB_USER;
const dbPassword = process.env.DB_PASSWORD;

通过 process.env 对象,你可以轻松地获取到在 .env 文件中定义的环境变量及其对应的值。

上面dotenv的使用过程是最普遍的,你可以传入一些可选的参数来定制其行为,同时还能在.env.vault文件设置加密密钥(具体如何在源码讲解中详细说明)

dotenv源码主体流程

dotenv源码:在lib/main..js里面

dotenv - npm (npmjs.com)

先来说明一下dotenv的源码的主体流程

引入 其他模块

const fs = require('fs')
const path = require('path')
const os = require('os')
const crypto = require('crypto')
const packageJson = require('../package.json')
const version = packageJson.version
  • fs 模块: fs 模块是 Node.js 中的文件系统模块,用于处理文件和目录的读写操作。通过 require('fs') 引入,可以使用其中的各种方法来进行文件的读取、写入、删除等操作。

  • path 模块:path模块是 Node.js 中的路径处理模块,用于处理文件路径。通过 require('path') 引入,可以使用其中的各种方法来处理文件路径,如路径的拼接、解析、规范化等。

  • os 模块:os 模块是 Node.js 中的操作系统信息模块,用于获取操作系统相关的信息。通过 require('os') 引入,可以使用其中的各种方法来获取操作系统的信息,如 CPU 核数、内存大小、操作系统类型等。

  • crypto 模块:crypto 模块是 Node.js 中的加密模块,用于提供各种加密功能。通过 require('crypto') 引入,可以使用其中的各种加密算法,如哈希、加密、解密等。

  • package.json 文件:package.json 文件是 Node.js 项目的配置文件,其中包含了项目的元数据信息,如项目名称、版本号、依赖项等。通过 require('../package.json') 引入,可以获取项目的配置信息,如版本号、依赖项等。

函数调用流程

当调用 config 入口方法时:

config方法首先调用_dotenvKey()判断是否存在 DOTENV_KEY。

如果存在 DOTENV_KEY,则调用 _configVault

  • _configVault调用 _parseVault解析 .env.vault文件。

  • _parseVault 调用_instructions()获取密文和密钥。

    _parseVault 调用 decrypt 进行解密。

    _parseVault 调用 parse 解析解密后的内容将其转换为键值对格式 。

  • _configVault 调用 populate 将解析结果添加到 process.env对象 中。

如果不存在DOTENV_KEY,则调用configDotenv

  • configDotenv 解析 .env 文件环境变量。

  • configDotenv 调用 parse解析文件内容并将其转换为键值对格式 。

  • configDotenv 调用 populate 将解析结果添加到 process.env对象 中。

导出模块接口

//定义 DotenvModule 对象
const DotenvModule = {
  configDotenv,
  _configVault,
  _parseVault,
  config,
  decrypt,
  parse,
  populate
}


//单独导出 DotenvModule 对象中的每个方法:
module.exports.configDotenv = DotenvModule.configDotenv
module.exports._configVault = DotenvModule._configVault
module.exports._parseVault = DotenvModule._parseVault
module.exports.config = DotenvModule.config
module.exports.decrypt = DotenvModule.decrypt
module.exports.parse = DotenvModule.parse
module.exports.populate = DotenvModule.populate


//导出整个 DotenvModule 对象:
module.exports = DotenvModule 

最后

dotenv源码具体解析敬请期待后续文章!

dotenv源码全面解析(上):

juejin.cn/post/737350…

image.png