git源码:git clone github.com/motdotla/do…
1、准备
克隆源码后,进入dotenv,读readme.md,按要求新建.env文件,并新建index.js文件,引入config.js文件,
NAME=若川
AGE=18
BLOG=https://lxchuan12.gitee.io
MP_WEIXIN='若川视野'
ACTIVITY="每周一起学200行左右的源码共读活动"
WEIXIN=加我微信 ruochuan12 参与
2、作用
- 读取 .env 文件
- 解析 .env 文件拆成键值对的对象形式
- 赋值到 process.env 上
- 最后返回解析后得到的对象
3、源码
1、config.js文件
(function () {
// console.log("argv", process.argv);
require("./lib/main").config(
Object.assign(
{},
require("./lib/env-options"),
require("./lib/cli-options")(process.argv)
)
);
})();
//合并options,做为main.js的config函数的参数
1、env-options.js
// ../config.js accepts options via environment variables
const options = {};
if (process.env.DOTENV_CONFIG_ENCODING != null) {
options.encoding = process.env.DOTENV_CONFIG_ENCODING;
}
if (process.env.DOTENV_CONFIG_PATH != null) {
options.path = process.env.DOTENV_CONFIG_PATH;
}
if (process.env.DOTENV_CONFIG_DEBUG != null) {
options.debug = process.env.DOTENV_CONFIG_DEBUG;
}
if (process.env.DOTENV_CONFIG_OVERRIDE != null) {
options.override = process.env.DOTENV_CONFIG_OVERRIDE;
}
module.exports = options;
2、cli-options.js
const re = /^dotenv_config_(encoding|path|debug|override)=(.+)$/
module.exports = function optionMatcher (args) {
return args.reduce(function (acc, cur) {
const matches = cur.match(re)
if (matches) {
acc[matches[1]] = matches[2]
}
return acc
}, {})
}
2、main.js
const fs = require("fs");
const path = require("path");
const os = require("os");
const LINE =
/(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\'|[^'])*'|\s*"(?:\"|[^"])*"|\s*`(?:\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/gm;
// Parser src into an Object
function parse(src) {
const obj = {};
// Convert buffer to string 将buffer变成字符串
let lines = src.toString();
// Convert line breaks to same format 格式化字符串
lines = lines.replace(/\r\n?/gm, "\n"); // /r结束符 /n换行符 /gm 全局 m 多行匹配
let match;
while ((match = LINE.exec(lines)) != null) {
const key = match[1];
// Default undefined or null to empty string
let value = match[2] || "";
// Remove whitespace
value = value.trim();
// Check if double quoted
const maybeQuote = value[0]; //若
// Remove surrounding quotes //去掉双引号、单引号
value = value.replace(/^(['"`])([\s\S]*)\12");
//$2 与 regexp 中的第 1 到第 99 个子表达式相匹配的文本
// Expand newlines if double quoted
if (maybeQuote === '"') {
value = value.replace(/\n/g, "\n");
value = value.replace(/\r/g, "\r");
}
// Add to object
obj[key] = value;
}
return obj;
}
function _log(message) {
console.log([dotenv][DEBUG] ${message});
}
function _resolveHome(envPath) {
return envPath[0] === "~"
? path.join(os.homedir(), envPath.slice(1))
: envPath;
}
// Populates process.env from .env file
function config(options) {
let dotenvPath = path.resolve(process.cwd(), ".env");
let encoding = "utf8";
const debug = Boolean(options && options.debug);
const override = Boolean(options && options.override);
if (options) {
if (options.path != null) {
dotenvPath = _resolveHome(options.path);
}
if (options.encoding != null) {
encoding = options.encoding;
}
}
try {
// Specifying an encoding returns a string instead of a buffer
const parsed = DotenvModule.parse(
fs.readFileSync(dotenvPath, { encoding })
);
console.log("parsed", parsed);
Object.keys(parsed).forEach(function (key) {
//判断key值是否属于process.env
if (!Object.prototype.hasOwnProperty.call(process.env, key)) {
process.env[key] = parsed[key];
} else {
if (override === true) {
process.env[key] = parsed[key];
}
if (debug) {
if (override === true) {
_log(
"${key}" is already defined in \process.env` and WAS overwritten`
);
} else {
_log(
"${key}" is already defined in \process.env` and was NOT overwritten`
);
}
}
}
});
return { parsed };
} catch (e) {
if (debug) {
_log(Failed to load ${dotenvPath} ${e.message});
}
return { error: e };
}
}
const DotenvModule = {
config,
parse,
};
module.exports.config = DotenvModule.config;
module.exports.parse = DotenvModule.parse;
module.exports = DotenvModule;
4、感谢
今天笔记写的有点乱 但是按照了自己的理解写的 看了7期源码 很感谢若川老师 不然我可能不会看源码 通过源码学习 了解了一些很高级的内容 我不会去写的代码 有很多感想 但是今天有点忙 哎呀 接着冲 最后真的很感谢若川老师