vue-cli脚手架源码解析(二)
前言:紧接上篇,这篇文章着重讲解create.js,这是创建项目的主文件。
从上而下,逐行解析。
- 先看依赖文件
const fs = require('fs-extra') // 这个是操作文件的库,node自带的库需要写很多的hack const path = require('path') // 路径 const chalk = require('chalk') // console上色 const inquirer = require('inquirer') // 这个很重要,是命令行交互用的,比如我们创建项目的时候,他会让你选择是否采用vue-router,是否使用vuex。 const Creator = require('./Creator') // 这个后面细说 const { clearConsole } = require('./util/clearConsole') // 这个就是console一些信息,不重要 const { getPromptModules } = require('./util/createTools') // 这个后面说 const validateProjectName = require('validate-npm-package-name') // 校验包名字,不重要
- 重点来看create方法,我删除一些不重要的内容
async function create (projectName, options) { // projectName就是我们创建的项目名字,比如hello-word // options就是我们输入的参数了,例如 -p -f -d const cwd = options.cwd || process.cwd() //运行脚手架的目录 const inCurrent = projectName === '.' // 项目名是否是个.(也可以理解为目录,如果是.就代表当前目录,不需要创建了) const name = inCurrent ? path.relative('../', cwd) : projectName const targetDir = path.resolve(cwd, projectName || '.') // 会创建目录 const result = validateProjectName(name) // 校验名字是否合理,例如是否有空格 // 校验错误流被我删除了,无外乎提示错误。 if (fs.existsSync(targetDir)) { // 目录是否存在 if (options.force) { //参数是否有-f,如果有就强制删除目录 await fs.remove(targetDir) } else { // 否则就让用户自己选择,是覆盖啊,合并啊,还是啥的 await clearConsole() // 输出一些提示吧,这个不重要 if (inCurrent) { // 如果是当前目录创建项目,给个confirm提示 const { ok } = await inquirer.prompt([ { name: 'ok', type: 'confirm', message: `Generate project in current directory?` } ]) if (!ok) { return } } else { / const { action } = await inquirer.prompt([ { name: 'action', type: 'list', message: `Target directory ${chalk.cyan(targetDir)} already exists. Pick an action:`, choices: [ { name: 'Overwrite', value: 'overwrite' }, { name: 'Merge', value: 'merge' }, { name: 'Cancel', value: false } ] } ]) if (!action) { return } else if (action === 'overwrite') { console.log(`\nRemoving ${chalk.cyan(targetDir)}...`) await fs.remove(targetDir) } } } } // 总结上面的一堆代码,就是创建一个项目目录,来放代码,如果目录存在是强制删除还是覆盖合并。 const creator = new Creator(name, targetDir, getPromptModules()) // 真正创建的代码在这里面去了。 // name就是项目名 // targetDir就是 path.resolve(cwd, projectName || '.')就是目录地址 // getPromptModules这个是引入第三方库 await creator.create(options) }
看下getPromptModules(),他引入了好多的库,这些库,在用户选择不同的初始化项目的时候用得到。
return [ 'babel', 'typescript', 'pwa', 'router', 'vuex', 'cssPreprocessors', 'linter', 'unit', 'e2e' ].map(file => require(`../promptModules/${file}`))
真正的创建看来还是要等到下一篇文章再说了,再重点介绍下inquirer这个库。
inquirer命令行交互的库,比如我们常见的
一个是让你手动输入,y或者n,一个是选择。
当所有的交互完成会,会返回一个对象,就是用户选择或者输入的值,后续的输出逻辑就依赖这个值。
const inquirer = require('inquirer'); inquirer.prompt([ { type: 'input', message: '请选择是否创建(y/n)', name: 'xory', default: 'y', }, { type: 'list', message: '你喜欢什么水果?', name: 'xig', default: '0', choices:['西瓜','苹果','香蕉'] }, { type: 'input', message: '请输入手机号:', name: 'phone', validate: function(val) { if(val.match(/\d{11}/g)) { // 校验位数 return true; } return "请输入11位数字"; } } ]).then(answer => { console.log(answer); // answer就是用户的输入 })
重点的方法就prompt,prompt接收一个数组,数组里面是一个配置对象,重点是type,不同的type需要配置不同的数据,比如当type是list的时候,需要传一个choices,用于给用户选择。
相关推荐
往后余生 2020-09-17
CXsilent 2020-09-16
webgm 2020-08-16
Lophole 2020-06-28
sqliang 2020-06-14
xcguoyu 2020-06-13
徐建岗网络管理 2020-06-11
前端开发Kingcean 2020-06-11
cbao 2020-06-10
yezitoo 2020-06-06
bigname 2020-06-04
前端开发Kingcean 2020-05-29
xiaofanguan 2020-05-29
ELEMENTS爱乐小超 2020-05-28
皖林 2020-05-11
wbczyh 2020-05-03
zuihaobushi 2020-04-30