背景介紹
在使用阿里雲的函數計算時,使用了其一鍵部署工具fun, fun 在使用時需要配置 ACCOUNT_ID、REGION、ACCESS_KEY_ID、ACCESS_KEY_SECRET=xxxxxxxxxx等信息。 在使用時直接在根目錄下創建.env文件,並寫入
ACCOUNT_ID=xxxxxxxx
REGION=cn-shanghai
ACCESS_KEY_ID=xxxxxxxxxxxx
ACCESS_KEY_SECRET=xxxxxxxxxx 即可直接完成配置。
出於好奇,對.env文件的使用稍作了瞭解。整理如下:
一、.env的作用
.env
文件是用來自定義配置的一個簡單方法,可以將一些不能在代碼中存儲的敏感/賬號數據從代碼中剝離出來,作爲環境變量存儲在環境中。
二、.env的使用方法
.env
文件通常不包含在版本控制內,它可能包含敏感的 API Key 或者 密碼。所有需要環境變量定義(不敏感的定義)的項目都需要創建一個.env.example
文件,這個環境變量包含他們自己定義的環境變量或者聯合開發包含的環境變量。項目合作開發者可以獨立的複製 .env.example
並且重命名爲.env
,並且修改爲正確的本地環境配置,存儲密碼key或者提供他們必要的值。 在這個使用方法中 .env
文件應該添加到.gitignore
文件中並且永遠不會被項目的合作者簽入/簽出。這個方法確保裏邊沒有敏感的 API Key 或者 密碼在版本控制中出現從而減少了安全風險,並且開發環境中的配置永遠不會告知合作開發者。
- 在根目錄下添加
.env
文件
eg:
DB_HOST=127.0.0.1
DB_NAME=timeseriesmonitor"
DB_PORT=5432
DB_USER=tsm
DB_UNSECURE=true
- 引入
dotenv
npm install dotenv
let dotenv = require('dotenv');
dotenv.config('./env');
console.log(process.env);
打印log如下:
{
...
DB_HOST: '127.0.0.1',
DB_NAME: 'timeseriesmonitor',
DB_PORT: '5432',
DB_UNSECURE: 'true',
DB_USER: 'tsm',
...
}
三、 關於dotenv
dotenv
是一個NPM包,其作用爲將.env
文件解析爲json對象,並對其中的key-value對通過process.env
將其賦值爲環境變量。之後便可通過process.env[key]
,eg: process.env.DB_HOST
獲取環境變量。
附dotenv源碼: dotenv/main.js
const fs = require('fs')
const path = require('path')
function log (message /*: string */) {
console.log(`[dotenv][DEBUG] ${message}`)
}
// Parses src into an Object
function parse (src /*: string | Buffer */, options /*: ?DotenvParseOptions */) /*: DotenvParseOutput */ {
const debug = Boolean(options && options.debug)
const obj = {}
// convert Buffers before splitting into lines and processing
src.toString().split('\n').forEach(function (line, idx) {
// matching "KEY' and 'VAL' in 'KEY=VAL'
const keyValueArr = line.match(/^\s*([\w.-]+)\s*=\s*(.*)?\s*$/)
// matched?
if (keyValueArr != null) {
const key = keyValueArr[1]
// default undefined or missing values to empty string
let value = keyValueArr[2] || ''
// expand newlines in quoted values
const len = value ? value.length : 0
if (len > 0 && value.charAt(0) === '"' && value.charAt(len - 1) === '"') {
value = value.replace(/\\n/gm, '\n')
}
// remove any surrounding quotes and extra spaces
value = value.replace(/(^['"]|['"]$)/g, '').trim()
obj[key] = value
} else if (debug) {
log(`did not match key and value when parsing line ${idx + 1}: ${line}`)
}
})
return obj
}
// Populates process.env from .env file
function config (options /*: ?DotenvConfigOptions */) /*: DotenvConfigOutput */ {
let dotenvPath = path.resolve(process.cwd(), '.env')
let encoding /*: string */ = 'utf8'
let debug = false
if (options) {
if (options.path != null) {
dotenvPath = options.path
}
if (options.encoding != null) {
encoding = options.encoding
}
if (options.debug != null) {
debug = true
}
}
try {
// specifying an encoding returns a string instead of a buffer
const parsed = parse(fs.readFileSync(dotenvPath, { encoding }), { debug })
Object.keys(parsed).forEach(function (key) {
if (!process.env.hasOwnProperty(key)) {
process.env[key] = parsed[key]
} else if (debug) {
log(`"${key}" is already defined in \`process.env\` and will not be overwritten`)
}
})
return { parsed }
} catch (e) {
return { error: e }
}
}
module.exports.config = config
module.exports.load = config
module.exports.parse = parse
參考: