Vue-cli 的 create 指令是如何创建项目文件的
栏目: JavaScript · 发布时间: 5年前
内容简介:Vue-cli 是创建 Vue 项目的一个好方法,之前只是使用,没有关注过内部结构是咋样的。最近在做一个组内项目的 cli 工具,参考了一下 Vue-cli 的实现方法。
Vue-cli 是创建 Vue 项目的一个好方法,之前只是使用,没有关注过内部结构是咋样的。最近在做一个组内项目的 cli 工具,参考了一下 Vue-cli 的实现方法。
Vue-cli 项目结构
Vue-cli ),是一个多 package 项目,使用 lerna 进行管理。package 内的 @vue 文件夹下有很多包:
其中与创建项目有关的包,我们主要需要关注 cli 和 cli-service。
@vue/cli
@vue/cli 包,就是我们平时执行的 bin 文件,入口是 @vue/cli/bin/vue.js。该文件会先检查用户当前使用的 node.js 版本是否符合要求。
之后使用 commander.js )来提供命令行指令接口。
program .command('create <app-name>') .description('create a new project powered by Vue-cli-service') .option('-p, --preset <presetName>', 'Skip prompts and use saved or remote preset') .option('-d, --default', 'Skip prompts and use default preset') .option('-i, --inlinePreset <json>', 'Skip prompts and use inline JSON string as preset') .option('-m, --packageManager <command>', 'Use specified npm client when installing dependencies') .option('-r, --registry <url>', 'Use specified npm registry when installing dependencies (only for npm)') .option('-g, --git [message]', 'Force git initialization with initial commit message') .option('-n, --no-git', 'Skip git initialization') .option('-f, --force', 'Overwrite target directory if it exists') .option('-c, --clone', 'Use git clone when fetching remote preset') .option('-x, --proxy', 'Use specified proxy when creating project') .option('-b, --bare', 'Scaffold project without beginner instructions') .action((name, cmd) => { const options = cleanArgs(cmd) if (minimist(process.argv.slice(3))._.length > 1) { console.log(chalk.yellow('\n Info: You provided more than one argument. The first one will be used as the app\'s name, the rest are ignored.')) } // --git makes commander to default git to true if (process.argv.includes('-g') || process.argv.includes('--git')) { options.forceGit = true } require('../lib/create')(name, options) })
commander 会帮助收集选项参数等内容,之后调用了
require('../lib/create')(name, options)
可以看到最终项目创建逻辑是在 ../lib/create 中执行的。
../lib/create
create.js 文件主要做了以下几件事:
- 检查项目初始化名称是否合法。
- 检查项目初始化目录是否存在,若存在提示用户选择覆盖、合并、取消进行操作。
- 初始化 Creator 类,并执行实例的 .create 方法。
Creator 类
我们直接来看一下 Creator 类的 create 方法,该方法主要做了以下事情:
-
初始化 preset
preset 用于指定初始化项目的具体配置,例如是否使用 babel、typescript 等。preset 可以通过执行命令行 工具 时指定,未指定时会在命令行中提供选项让使用者选择。
if (!preset) { if (cliOptions.preset) { // vue create foo --preset bar preset = await this.resolvePreset(cliOptions.preset, cliOptions.clone) } else if (cliOptions.default) { // vue create foo --default preset = defaults.presets.default } else if (cliOptions.inlinePreset) { // vue create foo --inlinePreset {...} try { preset = JSON.parse(cliOptions.inlinePreset) } catch (e) { error(`CLI inline preset is not valid JSON: ${cliOptions.inlinePreset}`) exit(1) } } else { preset = await this.promptAndResolvePreset() } }
之后会在 preset 中添加 @vue/cli-service 插件,该插件用于创建初始化项目的基础内容。
// inject core service preset.plugins['@vue/cli-service'] = Object.assign({ projectName: name }, preset, { bare: cliOptions.bare })
-
根据命令行选项,初始化git。
-
安装所有插件。
preset 初始化之后,就会生成 package.json 文件,所有插件作为依赖放在 package.json 中,使用 npm 或 yarn 来进行安装。
-
初始化 Generator 类,并执行实例的 generate 方法。
Generator 类用于提供插件的加载机制。加载所有插件的内容,放入初始化的项目中。我们之后会说。
-
插件内容加载完毕后,会生成新的 package.json 依赖,此时需要再次进行安装。
- 生成 README.md 文件。
- 进行第一次 git 提交。
- 命令行中打印初始化完成提示信息。
Generator 类
Generator 类是 Vue-cli 提供的与插件之间交流机制,编写插件时可利用这个机制,进行文件、package.json 依赖的修改,具体可见官方文档: https://cli.vuejs.org/dev-guide/plugin-dev.html#generator
它是怎么工作的呢?Generator 类初始化时,会给每个插件初始化一个 GeneratorAPI 类,作为插件与 cli 之间的接口。
// apply generators from plugins plugins.forEach(({ id, apply, options }) => { const api = new GeneratorAPI(id, this, options, rootOptions) apply(api, options, rootOptions, invoking) })
之后在 .generate 方法调用时,调用了自身的 .resolveFiles 方法,来获取所有的文件内容。
// wait for file resolve await this.resolveFiles()
文件内容获取后,进行 package.json 的写入,以及模板文件的写入:
this.files['package.json'] = JSON.stringify(this.pkg, null, 2) + '\n' // write/update file tree to disk await writeFileTree(this.context, this.files, initialFiles)
以上所述就是小编给大家介绍的《Vue-cli 的 create 指令是如何创建项目文件的》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。