Project Icon

dotenv

轻量级环境变量管理工具 适用于Node.js项目

dotenv为Node.js项目提供简单高效的环境变量管理。它从.env文件读取配置并加载到process.env,支持多行值和注释。除基本功能外,dotenv还具备预加载和变量扩展等高级特性。通过dotenvx扩展,可实现多环境管理和加密部署,增强了配置的安全性和灵活性。这种做法符合Twelve-Factor App理念,适合现代应用开发。

🎉 宣布 dotenvx随处运行,多环境,加密环境变量

 

dotenv NPM 版本

dotenv

Dotenv 是一个零依赖模块,它将 .env 文件中的环境变量加载到 process.env 中。将配置与代码分开存储在环境中基于 十二要素应用程序 方法论。

js-standard-style LICENSE codecov

🌱 安装

# 本地安装(推荐)
npm install dotenv --save

或者使用 yarn 安装?yarn add dotenv

🏗️ 使用

如何使用 dotenv 视频教程 youtube/@dotenvorg

在项目根目录创建一个 .env 文件(如果使用像 apps/backend/app.js 这样的单体仓库结构,请将其放在运行 app.js 进程的文件夹根目录):

S3_BUCKET="YOURS3BUCKET"
SECRET_KEY="YOURSECRETKEYGOESHERE"

在应用程序中尽早导入和配置 dotenv:

require('dotenv').config()
console.log(process.env) // 确认工作正常后删除此行

.. 或者使用 ES6?

import 'dotenv/config'

就是这样。process.env 现在包含了你在 .env 文件中定义的键和值:

require('dotenv').config()

...

s3.getBucketCors({Bucket: process.env.S3_BUCKET}, function(err, data) {})

多行值

如果你需要多行变量,例如私钥,现在支持带换行符的多行值(>= v15.0.0):

PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----
...
Kh9NV...
...
-----END RSA PRIVATE KEY-----"

或者,你可以使用双引号包裹字符串并使用 \n 字符:

PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\nKh9NV...\n-----END RSA PRIVATE KEY-----\n"

注释

可以在单独的行或内联添加注释:

# 这是一条注释
SECRET_KEY=YOURSECRETKEYGOESHERE # 注释
SECRET_HASH="something-with-a-#-hash"

注释从 # 开始,所以如果你的值包含 #,请用引号包裹它。这是 >= v15.0.0 及以后版本的一个重大变化。

解析

解析包含环境变量的文件内容的引擎可供使用。它接受一个字符串或 Buffer,并返回一个包含解析后的键和值的对象。

const dotenv = require('dotenv')
const buf = Buffer.from('BASIC=basic')
const config = dotenv.parse(buf) // 将返回一个对象
console.log(typeof config, config) // object { BASIC : 'basic' }

预加载

注意:考虑使用 dotenvx 而不是预加载。我现在正在使用(并推荐)这种方式。

它具有相同的目的(你不需要 require 和加载 dotenv),增加了更好的调试功能,并且适用于任何语言、框架或平台。 – motdotla

你可以使用 --require (-r) 命令行选项 来预加载 dotenv。这样做,你就不需要在应用程序代码中 require 和加载 dotenv。

$ node -r dotenv/config your_script.js

以下配置选项支持作为命令行参数,格式为 dotenv_config_<option>=value

$ node -r dotenv/config your_script.js dotenv_config_path=/custom/path/to/.env dotenv_config_debug=true

此外,你可以使用环境变量来设置配置选项。命令行参数将优先于这些。

$ DOTENV_CONFIG_<OPTION>=value node -r dotenv/config your_script.js
$ DOTENV_CONFIG_ENCODING=latin1 DOTENV_CONFIG_DEBUG=true node -r dotenv/config your_script.js dotenv_config_path=/custom/path/to/.env

变量扩展

你需要在一个变量中添加另一个变量的值?使用 dotenv-expand

命令替换

使用 dotenvx 来进行命令替换。

在 .env 文件中的某个变量中添加命令的输出。

# .env
DATABASE_URL="postgres://$(whoami)@localhost/my_database"
// index.js
console.log('DATABASE_URL', process.env.DATABASE_URL)
$ dotenvx run --debug -- node index.js
[dotenvx@0.14.1] injecting env (1) from .env
DATABASE_URL postgres://yourusername@localhost/my_database

同步

你需要在机器、环境或团队成员之间保持 .env 文件同步?使用 dotenvx 加密你的 .env 文件,并安全地将它们包含在源代码控制中。这仍然遵循十二要素应用程序规则,通过生成与代码分开的解密密钥。

多环境

使用 dotenvx 生成 .env.ci.env.production 文件等。

部署

你需要以云无关的方式部署你的秘密?使用 dotenvx 生成一个私有解密密钥,并在生产服务器上设置。

🌴 管理多环境

使用 dotenvx

在本地运行任何环境。创建一个 .env.ENVIRONMENT 文件,并使用 --env-file 加载它。简单直接,但灵活。

$ echo "HELLO=production" > .env.production
$ echo "console.log('Hello ' + process.env.HELLO)" > index.js

$ dotenvx run --env-file=.env.production -- node index.js
Hello production
> ^^

或者使用多个 .env 文件

$ echo "HELLO=local" > .env.local
$ echo "HELLO=World" > .env
$ echo "console.log('Hello ' + process.env.HELLO)" > index.js

$ dotenvx run --env-file=.env.local --env-file=.env -- node index.js
Hello local

更多环境示例

🚀 部署

使用 dotenvx

只需一个命令即可为你的 .env 文件添加加密。传递 --encrypt 标志。

$ dotenvx set HELLO Production --encrypt -f .env.production
$ echo "console.log('Hello ' + process.env.HELLO)" > index.js

$ DOTENV_PRIVATE_KEY_PRODUCTION="<.env.production 私钥>" dotenvx run -- node index.js
[dotenvx] injecting env (2) from .env.production
Hello Production

了解更多

📚 示例

查看使用dotenv与各种框架、语言和配置的示例

📖 文档

Dotenv暴露了四个函数:

  • config
  • parse
  • populate
  • decrypt

Config

config会读取你的.env文件,解析内容,将其分配给process.env,并返回一个包含已加载内容的parsed键或失败时的error键的对象。

const result = dotenv.config()

if (result.error) {
  throw result.error
}

console.log(result.parsed)

你还可以向config传递选项。

选项

path

默认值:path.resolve(process.cwd(), '.env')

如果包含环境变量的文件位于其他位置,可以指定自定义路径。

require('dotenv').config({ path: '/custom/path/to/.env' })

默认情况下,config会在当前工作目录中查找名为.env的文件。

可以将多个文件作为数组传入,它们将按顺序解析并与process.env(或设置了option.processEnv时的对应对象)合并。变量的第一个设置值将生效,除非设置了options.override标志,在这种情况下最后设置的值将生效。如果process.env中已存在某个值且未设置options.override标志,则该值不会被更改。

require('dotenv').config({ path: ['.env.local', '.env'] })
encoding

默认值:utf8

指定包含环境变量的文件的编码。

require('dotenv').config({ encoding: 'latin1' })
debug

默认值:false

开启日志记录以帮助调试某些键或值未按预期设置的原因。

require('dotenv').config({ debug: process.env.DEBUG })
override

默认值:false

用.env文件中的值覆盖机器上已经设置的任何环境变量。如果在option.path中提供了多个文件,覆盖也将在每个文件与下一个文件合并时使用。如果未设置override,则第一个值生效。设置了override后,最后一个值生效。

require('dotenv').config({ override: true })
processEnv

默认值:process.env

指定一个对象来写入你的密钥。默认为process.env环境变量。

const myObject = {}
require('dotenv').config({ processEnv: myObject })

console.log(myObject) // .env中的值
console.log(process.env) // 这没有被更改或写入

Parse

解析包含环境变量的文件内容的引擎可供使用。它接受一个字符串或Buffer,并返回一个包含解析后的键和值的对象。

const dotenv = require('dotenv')
const buf = Buffer.from('BASIC=basic')
const config = dotenv.parse(buf) // 将返回一个对象
console.log(typeof config, config) // object { BASIC : 'basic' }

选项

debug

默认值:false

开启日志记录以帮助调试某些键或值未按预期设置的原因。

const dotenv = require('dotenv')
const buf = Buffer.from('hello world')
const opt = { debug: true }
const config = dotenv.parse(buf, opt)
// 期望看到一条调试消息,因为缓冲区不是KEY=VAL格式

Populate

将.env文件内容填充到process.env的引擎可供使用。它接受一个目标、一个源和选项。这对于想要提供自己对象的高级用户很有用。

例如,自定义源:

const dotenv = require('dotenv')
const parsed = { HELLO: 'world' }

dotenv.populate(process.env, parsed)

console.log(process.env.HELLO) // world

例如,自定义源和目标:

const dotenv = require('dotenv')
const parsed = { HELLO: 'universe' }
const target = { HELLO: 'world' } // 空对象

dotenv.populate(target, parsed, { override: true, debug: true })

console.log(target) // { HELLO: 'universe' }

选项

Debug

默认值:false

开启日志记录以帮助调试某些键或值未按预期填充的原因。

override

默认值:false

覆盖任何已经设置的环境变量。

❓ 常见问题

为什么.env文件没有成功加载我的环境变量?

很可能你的.env文件位置不正确。参见这个Stack Overflow问题

打开调试模式再试一次..

require('dotenv').config({ debug: true })

你会在控制台看到一条有用的错误输出。

我应该提交我的.env文件吗?

不。我们强烈建议不要将你的.env文件提交到版本控制。它应该只包含特定环境的值,如数据库密码或API密钥。你的生产数据库应该有一个与开发数据库不同的密码。

我应该有多个.env文件吗?

我们建议为每个环境创建一个.env文件。对本地/开发使用.env,对生产使用.env.production,以此类推。这仍然遵循十二因素原则,因为每个文件都单独归属于其自己的环境。避免使用以某种方式继承的自定义设置(例如,.env.production.env继承值)。如果需要,最好在每个.env.environment文件中复制值。

在十二因素应用中,环境变量是细粒度的控制,每个变量完全独立于其他环境变量。它们从不被归类为"环境",而是为每次部署独立管理。这是一个随着应用自然扩展到更多部署而平滑扩展的模型。

十二因素应用

解析引擎遵循哪些规则?

解析引擎目前支持以下规则:

  • BASIC=basic 变为 {BASIC: 'basic'}
  • 空行被跳过
  • # 开头的行被视为注释
  • # 标记注释的开始(除非值被引号包裹)
  • 空值变为空字符串(EMPTY= 变为 {EMPTY: ''}
  • 内部引号保持不变(考虑JSON)(JSON={"foo": "bar"} 变为 {JSON:"{\"foo\": \"bar\"}")
  • 未加引号的值两端的空白会被移除(参见trim)(FOO= some value 变为 {FOO: 'some value'}
  • 单引号和双引号值会被转义(SINGLE_QUOTE='quoted' 变为 {SINGLE_QUOTE: "quoted"}
  • 单引号和双引号值保留两端的空白(FOO=" some value " 变为 {FOO: ' some value '}
  • 双引号值展开新行(MULTILINE="new\nline" 变为
{MULTILINE: 'new
line'}
  • 支持反引号(BACKTICK_KEY=`This has 'single' and "double" quotes inside of it.`

已经设置的环境变量会发生什么?

默认情况下,我们永远不会修改任何已经设置的环境变量。特别是,如果你的.env文件中有一个变量与已存在的环境变量冲突,那么该变量将被跳过。

如果你想覆盖process.env,请使用override选项。

require('dotenv').config({ override: true })

为什么我的环境变量在React中不显示?

你的React代码在Webpack中运行,其中fs模块甚至process全局变量本身都无法开箱即用。process.env只能通过Webpack配置注入。

如果你使用的是通过create-react-app分发的react-scripts,它内置了dotenv,但有一个特点。在你的环境变量前加上REACT_APP_前缀。有关更多详细信息,请参阅这个Stack Overflow问题

如果你使用其他框架(如Next.js、Gatsby等),你需要查阅它们的文档,了解如何将环境变量注入到客户端。

我可以为dotenv自定义/编写插件吗?

可以!dotenv.config()返回一个表示已解析.env文件的对象。这为你提供了继续在process.env上设置值所需的一切。例如:

const dotenv = require('dotenv')
const variableExpansion = require('dotenv-expand')
const myEnv = dotenv.config()
variableExpansion(myEnv)

如何在import中使用dotenv?

简单来说..

// index.mjs (ESM)
import 'dotenv/config' // 参见 https://github.com/motdotla/dotenv#how-do-i-use-dotenv-with-import
import express from 'express'

一些背景..

当你运行包含import声明的模块时,它导入的模块会先被加载,然后每个模块的主体会按照依赖图的深度优先遍历顺序执行,通过跳过已执行的内容来避免循环。

ES6深入:模块

用简单的话来说,这意味着你可能会认为以下代码可以正常工作,但实际上并不行。

errorReporter.mjs:

import { Client } from 'best-error-reporting-service'

export default new Client(process.env.API_KEY)

index.mjs:

// 注意:这是错误的,不会生效
import * as dotenv from 'dotenv'
dotenv.config()

import errorReporter from './errorReporter.mjs'
errorReporter.report(new Error('documented example'))

process.env.API_KEY将会是空白的。

相反,index.mjs应该这样写:

import 'dotenv/config'

import errorReporter from './errorReporter.mjs'
errorReporter.report(new Error('documented example'))

这样理解了吗?这有点不直观,但这就是ES6模块导入的工作方式。这里有一个这种陷阱的实际例子

还有两种替代方法:

  1. 预加载dotenv:node --require dotenv/config index.js(注意:使用这种方法不需要import dotenv)
  2. 创建一个单独的文件,首先执行config,如这个关于#133的评论中所述

为什么我会收到Module not found: Error: Can't resolve 'crypto|os|path'这个错误?

你在前端使用dotenv时没有包含polyfill。Webpack 5以下版本曾为你包含这些。请执行以下操作:

npm install node-polyfill-webpack-plugin

将你的webpack.config.js配置为类似以下内容:

require('dotenv').config()

const path = require('path');
const webpack = require('webpack')

const NodePolyfillPlugin = require('node-polyfill-webpack-plugin')

module.exports = {
  mode: 'development',
  entry: './src/index.ts',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist'),
  },
  plugins: [
    new NodePolyfillPlugin(),
    new webpack.DefinePlugin({
      'process.env': {
        HELLO: JSON.stringify(process.env.HELLO)
      }
    }),
  ]
};

或者,直接使用dotenv-webpack,它会在后台为你处理这些事情。

变量扩展怎么办?

试试dotenv-expand

如何同步和保护.env文件?

使用dotenvx

如果我不小心将.env文件提交到代码中怎么办?

删除它,删除git历史,然后安装git pre-commit钩子以防止这种情况再次发生。

brew install dotenvx/brew/dotenvx
dotenvx precommit --install

如何防止将.env文件提交到Docker构建中?

使用docker prebuild钩子

# Dockerfile
...
RUN curl -fsS https://dotenvx.sh/ | sh
...
RUN dotenvx prebuild
CMD ["dotenvx", "run", "--", "node", "index.js"]

贡献指南

请参阅CONTRIBUTING.md

更新日志

请参阅CHANGELOG.md

谁在使用dotenv?

这些npm模块依赖于它。

扩展它的项目通常在npm上使用"dotenv"关键词

项目侧边栏1项目侧边栏2
推荐项目
Project Cover

豆包MarsCode

豆包 MarsCode 是一款革命性的编程助手,通过AI技术提供代码补全、单测生成、代码解释和智能问答等功能,支持100+编程语言,与主流编辑器无缝集成,显著提升开发效率和代码质量。

Project Cover

AI写歌

Suno AI是一个革命性的AI音乐创作平台,能在短短30秒内帮助用户创作出一首完整的歌曲。无论是寻找创作灵感还是需要快速制作音乐,Suno AI都是音乐爱好者和专业人士的理想选择。

Project Cover

有言AI

有言平台提供一站式AIGC视频创作解决方案,通过智能技术简化视频制作流程。无论是企业宣传还是个人分享,有言都能帮助用户快速、轻松地制作出专业级别的视频内容。

Project Cover

Kimi

Kimi AI助手提供多语言对话支持,能够阅读和理解用户上传的文件内容,解析网页信息,并结合搜索结果为用户提供详尽的答案。无论是日常咨询还是专业问题,Kimi都能以友好、专业的方式提供帮助。

Project Cover

阿里绘蛙

绘蛙是阿里巴巴集团推出的革命性AI电商营销平台。利用尖端人工智能技术,为商家提供一键生成商品图和营销文案的服务,显著提升内容创作效率和营销效果。适用于淘宝、天猫等电商平台,让商品第一时间被种草。

Project Cover

吐司

探索Tensor.Art平台的独特AI模型,免费访问各种图像生成与AI训练工具,从Stable Diffusion等基础模型开始,轻松实现创新图像生成。体验前沿的AI技术,推动个人和企业的创新发展。

Project Cover

SubCat字幕猫

SubCat字幕猫APP是一款创新的视频播放器,它将改变您观看视频的方式!SubCat结合了先进的人工智能技术,为您提供即时视频字幕翻译,无论是本地视频还是网络流媒体,让您轻松享受各种语言的内容。

Project Cover

美间AI

美间AI创意设计平台,利用前沿AI技术,为设计师和营销人员提供一站式设计解决方案。从智能海报到3D效果图,再到文案生成,美间让创意设计更简单、更高效。

Project Cover

AIWritePaper论文写作

AIWritePaper论文写作是一站式AI论文写作辅助工具,简化了选题、文献检索至论文撰写的整个过程。通过简单设定,平台可快速生成高质量论文大纲和全文,配合图表、参考文献等一应俱全,同时提供开题报告和答辩PPT等增值服务,保障数据安全,有效提升写作效率和论文质量。

投诉举报邮箱: service@vectorlightyear.com
@2024 懂AI·鲁ICP备2024100362号-6·鲁公网安备37021002001498号