- 简介
dotenv是一个读取.env文件的工具库,能够将.env文件中的环境变量读取到process.env中,使得在程序中可以方便地访问环境变量。本篇文章将从源码角度简要介绍dotenv的实现机制。
- 源码解读
dotenv库的主要代码存放在dotenv-webpack和dotenv两个仓库中,可从github上进行下载,下面是dotenv的主要源码解读:
首先,我们需要了解一些dotenv的用法。
require('dotenv').config()
这个命令会从当前目录中的.env文件中读取环境变量,并把这些变量存储到process.env中。我们可以在代码中使用process.env来访问这些变量。
dotenv库的实现很简单,它顺序执行以下步骤:
(1) 指定.env文件所在的路径
(2) 读取.env中的所有环境变量
(3) 将环境变量存储到process.env中
下面我们逐步分析这些步骤。
首先,我们可以看到dotenv库中的config操作,它是dotenv库最为核心的方法,文件实现代码如下:
function config(options: DotenvConfigOptions = {}): DotenvParseOutput {
if (options.path) {
const envConfig = parse(fs.readFileSync(options.path, { encoding: 'utf8' }))
for (const k in envConfig) {
if (!Object.prototype.hasOwnProperty.call(process.env, k)) {
process.env[k] = envConfig[k]
}
}
return envConfig
}
if (options.encoding) {
console.warn('config() `options.encoding` is deprecated. Use `options.encoding` instead.')
}
const path = findUpSync('.env', { cwd: options.cwd ?? process.cwd() })
if (path === null) {
return {}
}
return config({ ...options, path })
}
从上面的代码片段中,我们可以看到doten库主要的实现逻辑:
- options.path指定.env文件的路径。
- 通过fs.readFileSync同步读取.env文件内容。
- 将.env文件中的所有key-value对进行解析。
- 将解析结果写入到process.env中。
实现步骤非常简单,主要是使用了一些node.js固有的库,具体实现请看下面的代码,其中parse方法实现很简单,直接把字符串按照换行符和等于号进行切割,生成一个键值对,如下:
export function parse(src: string, options?: DotenvParseOptions): DotenvParseOutput {
const debug = createDebug('dotenv:parse')
const debugKey = createDebug('dotenv:key')
const vars = {}
const newline = /\r\n|[\n\r\u2028\u2029]/g
// 先用\n分割字符串,然后用=分割key-value,去掉空格
src.split(newline).forEach((line, idx) => {
// matching "KEY' and 'VAL' in 'KEY=VAL'
const keyValueArr = line.match(/^\s*([\w.-]+)\s*=\s*(.*)?\s*$/)
if (keyValueArr != null && keyValueArr.length > 1) {
const key = keyValueArr[1]
let val = (keyValueArr[2] || '')
const end = val.length - 1
const isDoubleQuoted = val[0] === '"' && val[end] === '"'
const isSingleQuoted = val[0] === "'" && val[end] === "'"
if (isSingleQuoted || isDoubleQuoted) {
// remove quotes
val = val.substring(1, end)
if (isDoubleQuoted) {
// handle escaped characters
val = val.replace(/\\([\s\S])|(")/g, '$1')
}
} else {
// interpret variables
val = expandVariables(val, vars)
}
debugKey('%s=%s', key, val)
vars[key] = val
} else {
const lineNumber = idx + 1
if (line.trim() && !options?.ignoreProcessEnv) {
console.warn(`dotenv: Invalid line ${lineNumber} in file ${options?.path ?? '.env' }: ${line}`)
}
}
})
return vars
}
- 示例说明
(1) 读取.env文件中的环境变量
首先,创建一个.env文件,内容如下:
TEST=hello world
DB_HOST=localhost
DB_USER=root
DB_PASSWORD=123456
DB_PORT=3306
然后,我们在我们的项目中创建一个main.js文件,代码如下:
require('dotenv').config()
console.log(process.env.TEST) // 输出 hello world
console.log(process.env.DB_HOST) // 输出 localhost
console.log(process.env.DB_USER) // 输出 root
console.log(process.env.DB_PASSWORD) // 输出 123456
console.log(process.env.DB_PORT) // 输出 3306
在项目根目录执行 node main.js 命令即可查看结果。
(2) 指定.env文件的路径
有时候项目根目录并不是.env文件的目录,我们可以使用path
配置项指定.env文件的目录:
require('dotenv').config({ path: '/custom/path/to/.env' })
这样dotenv在加载.env文件时,就会使用指定的路径。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:dotenv源码解读从.env文件中读取环境变量 - Python技术站