闽公网安备 35020302035485号
一.阅读本文,你将学到:
1. 学会 dotenv 原理和实现3. 等等
# 推荐克隆我的项目,保证与文章同步 git clone https://github.com/lxchuan12/dotenv-analysis.git # npm i -g yarn cd dotenv-analysis/dotenv && yarn i # VSCode 直接打开当前项目 # code . # 我写的例子都在 examples 这个文件夹中,可以启动服务本地查看调试 # 在 dotenv-analysis 目录下 node examples/index.js # 或者克隆官方项目 git clone https://github.com/motdotla/dotenv.git # npm i -g yarn cd dotenv && yarn i # VSCode 直接打开当前项目 # code .如果需要对源码进行调试,可以看我的这篇文章:新手向:前端程序员必学基本技能——调试JS代码,这里就不再赘述了。
NAME=若川 AGE=18 BLOG=https://www.duidaima.com MP_WEIXIN='堆代码' ACTIVITY=每周一起学200行左右的源码共读活动 WEIXIN=加我微信 duidaima参与单从这个文件来看,我们可以知道有如下功能需要实现:
最后返回解析后得到的对象
const fs = require('fs');
const path = require('path');
const parse = function parse(src){
const obj = {};
// 用换行符 分割
// 比如
src.toString().split('\n').forEach(function(line, index){
// 用等号分割
const keyValueArr = line.split('=');
// NAME
key = keyValueArr[0];
val = keyValueArr[1] || '';
obj[key] = val;
});
// { NAME: '若川', ... }
return obj;
}
const config = function(){
// 读取 node 执行的当前路径下的 .env 文件
let dotenvPath = path.resolve(process.cwd(), '.env');
// 按 utf-8 解析文件,得到对象
// { NAME: '若川', ... }
const parsed = parse(fs.readFileSync(dotenvPath, 'utf-8'));
// 键值对形式赋值到 process.env 变量上,原先存在的不赋值
Object.keys(parsed).forEach(function(key){
if(!Object.prototype.hasOwnProperty.call(process.env, key)){
process.env[key] = parsed[key];
}
});
// 返回对象
return parsed;
};
console.log(config());
console.log(process.env);
// 导出 config parse 函数
module.exports.config = config;
module.exports.parse = parse;
六. 继续完善 config 函数function resolveHome (envPath) {
return envPath[0] === '~' ? path.join(os.homedir(), envPath.slice(1)) : envPath
}
const config = function(options){
// 读取 node 执行的当前路径下的 .env 文件
let dotenvPath = path.resolve(process.cwd(), '.env');
// utf8
let encoding = 'utf8';
// debug 模式,输出提示等信息
let debug = false;
// 对象
if (options) {
if (options.path != null) {
// 解析路径
dotenvPath = resolveHome(options.path)
}
// 使用配置的编码方式
if (options.encoding != null) {
encoding = options.encoding
}
// 有配置就设置为 true
if (options.debug != null) {
debug = true
}
}
try {
// 按 utf-8 解析文件,得到对象
// debug 传递给 parse 函数 便于
const parsed = parse(fs.readFileSync(dotenvPath, { encoding }), { debug });
// 键值对形式赋值到 process.env 变量上,原先存在的不赋值
Object.keys(parsed).forEach(function(key){
if(!Object.prototype.hasOwnProperty.call(process.env, key)){
process.env[key] = parsed[key];
} else if (debug) {
console.log(`"${key}" is already defined in \`process.env\` and will not be overwritten`);
}
});
// 返回对象
return parsed;
}
catch (e) {
return { error: e };
}
};
dotenv 源码中,parse 函数主要是一些正则和单双引号、跨平台等细致处理。这里就暂时不阐述,读者朋友可以查看dotenv 源码[7]。