新版本 Vue CLI 最常用的一个命令了,用来新建一个项目:
vue createdemo
对应的描述如下:
create a new project powered byvue-cli-service
我们还是先看@vue/cli/bin/vue.js
这里它的option很多(设计和实际应用也要考虑),大家使用的时候可以查看:
program
.command('create ')
.description('create a new project powered by vue-cli-service')
.option('-p, --preset
', 'Skip prompts and use saved or remote preset')
.option('-d, --default', 'Skip prompts and use default preset')
.option('-i, --inlinePreset ', 'Skip prompts and use inline JSON string as preset')
.option('-m, --packageManager ', 'Use specified npm client when installing dependencies')
.option('-r, --registry ', '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)
// --no-git makes commander to default git to true
options.forceGit = true
}
require('../lib/create')(name, options)
})
具体我们看看@vue/cli/lib/create.js文件
定义了create函数,接受 2 个参数:
projectName
options
async function create (projectName, options) {
// ...
}
在 create.js 文件中它做了很多检查验证工作:
比如会验证项目名字:使用了工具包validate-npm-package-name
const validateProjectName = require('validate-npm-package-name')
const result = validateProjectName(name)
会判断新的项目目录是否已经存在,等等,非本文重点,大家感兴趣可以查看
直接到了:
const creator = newCreator(name, targetDir, getPromptModules())
这里的 Creator 来自文件 Creator.js
const Creator = require('./Creator')
这里的 getPromptModules 来自 util/createTools.js
const { getPromptModules } = require('./util/createTools')
我们看一下Creator.js文件结构:
module.exports = class Creator extends EventEmitter {
constructor (name, context, promptModules) {}
async create (cliOptions = {}, preset = null) {}
}
然后在命令行会让你选择:
Vue CLI v3.0.1
?Please pick a preset:(Use arrow keys)
❯ default (babel,eslint)
Manually select features
我们看一下函数 promptAndResolvePreset:
async promptAndResolvePreset (answers = null) {
}
函数内部,最核心还是inquirer.prompt
if (!answers) {
await clearConsole(true)
answers = awaitinquirer.prompt(this.resolveFinalPrompts())
}
这里也看一下clearConsole函数:
会获取一次版本
const getVersions = require('./getVersions')
const { current, latest } = await getVersions()
这里取回来当前和最新的版本多是:3.0.1,所以展示了上面的那个信息
const presetPrompt = {
name: 'preset',
type: 'list',
message: `Please pick a preset:`,
choices: [
...presetChoices,
{
name: 'Manually select features',
value: '__manual__'
}
]
}
这里还套了一层,如果你选了Manually select features,如下:
关于 git 的设置:
const shouldInitGit = await this.shouldInitGit(cliOptions)
核心还是通过git init来创建 git 项目
if (shouldInitGit) {
logWithSpinner(``, `Initializing git repository...`)
this.emit('creation', { event: 'git-init' })
await run('git init')
}
我们看一下 shouldInitGit 函数设计:默认是 true
async shouldInitGit (cliOptions) {
if (!hasGit()) {
return false
}
// --git
if (cliOptions.forceGit) {
return true
}
// --no-git
if (cliOptions.git === false || cliOptions.git === 'false') {
return false
}
// default: true unless already in a git repo
return !hasProjectGit(this.context)
}
写入文件部分:
1、package.json
await writeFileTree(context, {
'package.json': JSON.stringify(pkg, null, 2)
})
2、generator
const plugins = await this.resolvePlugins(preset.plugins)
在 resolvePlugins 函数中会一个一个找:
/@vue/cli-service/generator/index.js
@vue/cli-plugin-babel/generator.js
@vue/cli-plugin-eslint/generator.js
const generator = new Generator(context, {
pkg,
plugins,
completeCbs: createCompleteCbs
})
还是调用 Generator.js 文件
const Generator = require('./Generator')
await generator.generate({
extractConfigFiles: preset.useConfigFiles
})
我们选择default (babel,eslint) 后对应的 preset 如下:
preset { router: false,
vuex: false,
useConfigFiles: false,
cssPreprocessor: undefined,
plugins:
{ '@vue/cli-plugin-babel': {},
'@vue/cli-plugin-eslint': { config: 'base', lintOn: [Array] } } }
可以看一下cli-service的generator目录:
关于依赖的安装:
const { installDeps } = require('./util/installDeps')
函数installDeps的结构:
exports.installDeps = async function installDeps (targetDir, command, cliRegistry) {
}
函数内部会针对 command 的类型来处理:
command 是npm
const args = []
if (command === 'npm') {
args.push('install', '--loglevel', 'error')
}
await addRegistryToArgs(command, args, cliRegistry)
具体如下:
command:npm
args:[ 'install',
'--loglevel',
'error',
'--registry=https://registry.npm.taobao.org',
'--disturl=https://npm.taobao.org/dist' ]
领取专属 10元无门槛券
私享最新 技术干货