源码系列之 create

新版本 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' ]

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180828G0BP9Y00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券