在/umi/lib/forkedDev.js中有这么几行核心代码,还引入了好几个文件,好复杂,现在一一解析一下
var _ServiceWithBuiltIn = require("./ServiceWithBuiltIn");
var _getCwd = _interopRequireDefault(require("./utils/getCwd"));
var _getPkg = _interopRequireDefault(require("./utils/getPkg"));
const service = new _ServiceWithBuiltIn.Service({
cwd: (0, _getCwd.default)(),
pkg: (0, _getPkg.default)(process.cwd())
});
yield service.run({
name: 'dev',
args
});
目录
_ServiceWithBuiltIn /umi/lib/ServiceWithBuiltIn.js
_getCwd /umi/utils/getCwd.js
文件内部核心代码如下:
var _default = () => {
//获取umi 项目的根路径。
let cwd = process.cwd();
if (process.env.APP_ROOT) {
// avoid repeat cwd path
if (!(0, _path().isAbsolute)(process.env.APP_ROOT)) {
return (0, _path().join)(cwd, process.env.APP_ROOT);
}
return process.env.APP_ROOT;
}
return cwd;
};
exports.default = _default;
主要功能就是利用获取node命令执行的路径,获取项目的绝对路径,但里面那个APP_ROOT的变量判断不是很懂
_getPkg /umi/utils/getPkg.js
文件内部核心代码如下:
var _default = dir => {
try {
return require((0, _path().join)((0, _getCwd.default)(), 'package.json'));
} catch (error) {
try {
return require((0, _path().join)(dir, 'package.json'));
} catch (error) {
return null;
}
}
};
exports.default = _default;
主要功能就是根据绝对路径拼接获得package.json文件的路径
_ServiceWithBuiltIn /umi/lib/ServiceWithBuiltIn.js
class Service extends _core().Service {
constructor(opts) {
process.env.UMI_VERSION = require('../package').version;
process.env.UMI_DIR = (0, _path().dirname)(require.resolve('../package'));
super(_objectSpread(_objectSpread({}, opts), {}, {
presets: [require.resolve('@umijs/preset-built-in'), ...(opts.presets || [])],
plugins: [require.resolve('./plugins/umiAlias'), ...(opts.plugins || [])]
}));
}
}
这个Service 继承了 CoreService,对其进行了加强。
process.env.UMI_VERSION process.env.UMI_DIR //path模块的学习
进行全局环境变量的配置
然后我们发现他企图通过父类的构造函数来初始化,但对这个传参利用_objectSpread进行了比较复杂的处理,我们先一一分析一下这个参数是怎么做到的。
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
super(_objectSpread(_objectSpread({}, opts), {}, {
presets: [require.resolve('@umijs/preset-built-in'), ...(opts.presets || [])],
plugins: [require.resolve('./plugins/umiAlias'), ...(opts.plugins || [])]
}));
在这里我先介绍一下es6里面的几个新的方法,我之前也没见过
Object.getOwnPropertySymbols:获取以Symbol为对象的属性名数组(Obj.keys()获取不到) Object.getOwnPropertyDescriptor:一个参数:此方法返回规定对象的所有属性,包括getter、seter,允许我们在创建副本的对象并复制所有属性克隆他;两个参数:如果指定的属性存在于对象上,则返回其属性描述符对象(property descriptor,包含value,writerable..),否则返回 undefined(enumerable:当且仅当指定对象的属性可以被枚举出时,为true。)、 可枚举性:若为false,在利用 for..in.. Objkect.keys JSON.stringfy时不会显示该属性在这里对比一下自带的几个获取属性键值的函数
Object.keys():返回属性key,但不包括不可枚举的属性、Symbol对象的属性
Reflect.ownKeys():返回所有属性输出
Object.getOwnPropertySymbols:返回所有Symbol对象的属性
ownKeys:获取该对象的所有拥有的key(视情况去除不可枚举的symbol对象的key) 利用Object.keys获取键值,如果Object.getOwnPropertySymbols函数存在的话,就将Sybmol对象的键值也获取进来。如果设置仅需要可枚举属性的话,会对Sybmol键值进行过滤(利用Object.getOwnPropertyDescriptor判断是否是可枚举属性)。将获取到的键值组合并返回
_defineProperty:设置obj[key]=value
然后对这个CoreService追溯,在@umijs/core/Service/Service.js中,进一步解析