来了,老弟!
上一节我们讲到create这个方法,现在我们具体来解析:
还是一样,打开以下几个文件
只要剖析完这个create方法,你会发现整个Creator.js这个文件你都消化了
首先,请安耐住你焦躁的心情,因为篇幅会比较长,但只要耐心看完,哪怕多花点时间,相信会有不一样的收获~~~😋
伪代码
话不多说,先上伪代码:
async create(cliOptions = {}, preset = null){
if(<预置属性presets> = 空){
if(vue create foo --preset bar) 获取用户自定义prese[本地、远程preset]
if(vue create foo --default) 跳过询问直接使用默认<预置属性presets>
if(vue create foo --inlinePreset) 跳过询问直接使用默认预置属性并使用用户输入的<预置属性presets>
else promptAndResolvePreset(){
✨ 询问用户...
如果 用户选择自定义
则 初始化preset{useConfigFiles,plugins}并回调处理用户答案
否则 resolvePreset(){
getPresets 获取~/.vuerc presets 和 默认presets合并的结果
直接读取刚合并的结果 || 读取指定文件 || 读取远程文件
如果都没有获取到对应的<预置属性presets>,则 报错
}
⚙ 配置对应的<插件plugins>属性
《1》设置包管理器 yar/npm or more
根据<插件plugins>生成package.json
判断是否可以安全初始化Git 并执行 git init
📦 安装依赖install
🚀 《2》构建工程及README.md
执行 git add 并打印 🎉 Successfully
}
}
}
550+代码做的事情大致就浓缩在以上伪代码中,是不是很酷 😎
当然,只看伪代码是不够的,很多细节和优雅的实现我们得看源代码,伪代码只是辅助你了解其构造,最好是比照着源代码去阅读
“源”来如此
首先我们先Po出该文件内部引用的一些工具和依赖的说明,也可以先跳过此部分;
* 阅读容易 ** 阅读一般 *** 阅读困难
sortObject | 按照KEY排序对象 | * |
getVersions | 获取相关版本号 | ** |
ProjectPackageManager | 融合包管理器 | *** |
clearConsole | 控制台清除并打印信息 | * |
PromptModuleAPI | 询问API | * |
writeFileTree | 写入文件树 | * |
features | 收集特性、格式化 | * |
loadLocalPreset | 获取指定位置的文件preset | * |
loadRemotePreset | 获取远程preset | * |
generateReadme | 生成README.md | * |
@vue/cli-shared-utils 依赖
resolvePkg
获取指定环境的package.json *
isOfficialPlugin
判断该插件是否符合@vue命名 *
Creator.js中,首先映入眼帘的是这一句
module.exports = class Creator extends EventEmitter
EventEmitter????这是个啥, 听这个名字就觉得是个大工具啊。
往上查找,哦,放心了,是第三方依赖库
在create方法中会出现以下语句:
this.emit('creation', { event: 'creating' })
Events
模块是Node对“发布/订阅”模式(publish/subscribe
)的实现
这里我们只需要了解到这些即可
虽然create方法很长,但也好在大神在每个功能段落都有加注释,一段段去理解也不是很难的事情嘛
《1》设置包管理器 yar/npm or more
不同的客户端使用的包管理器不一样,为了统一行为,这里提供了一个工具 ProjectPackageManager
const pm = new PackageManager({ context, forcePackageManager: packageManager })
打开ProjectPackageManager.js可以看到:
看到熟悉的install大致可以猜到这个文件是用来统一不同包管理器的行为。
《2》构建工程及README.md
// run generator
log(`🚀 Invoking generators...`)
this.emit('creation', { event: 'invoking-generators' })
const plugins = await this.resolvePlugins(preset.plugins, pkg)
const generator = new Generator(context, {
pkg,
plugins,
afterInvokeCbs,
afterAnyInvokeCbs
})
await generator.generate({
extractConfigFiles: preset.useConfigFiles
})
Generator类,我点进去一看,啊,又是360+的代码量,我又慌了,朋友们,下次再见 👋🏻 😄
小技巧:
// 来源:features.js
features.push.apply(features, plugins)
// 其实相当于
features = features.concat(plugins)
process.cwd()
// 获取 node 当前工作目录