vue-cli脚手架 vue和vue-cli-service命令详解

create

vue create 后面有很多参数:

源码如下:

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('--merge', 'Merge 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')
  .option('--skipGetStarted', 'Skip displaying "Get started" 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)
  })

从上面的代码可以很清楚的看出vue create后面跟的参数

vue create执行过程

vue create ===>

create.js ===>

Creator.js ===>

如果有preset加载preset ===>

OS模块创建系统临时文件夹(os 模块提供了一些基本的系统操作函数)===> 

有远程preset,使用download-git-repo下载仓库 ===>

从临时文件夹获取内容写入到实际文件夹(通过fs模块操作)

vue-cli-service

vue-cli-service就像create-react-app的react-scripts, 将项目打包,启动等命令集成到了该命令中,在源码中对应的包是packages/vue/cli-service

如图:

入口文件会指向Service.js

const Service = require('../lib/Service')
const service = new Service(process.env.VUE_CLI_CONTEXT || process.cwd())

const rawArgv = process.argv.slice(2)
const args = require('minimist')(rawArgv, {
  boolean: [
    // build
    'modern',
    'report',
    'report-json',
    'inline-vue',
    'watch',
    // serve
    'open',
    'copy',
    'https',
    // inspect
    'verbose'
  ]
})
const command = args._[0]

service.run(command, args, rawArgv).catch(err => {
  error(err)
  process.exit(1)
})

Serveice.js

执行constructor()实例化===>

this.pkg = this.resolvePkg(pkg) ===>

this.plugins = this.resolvePlugins(plugins, useBuiltIn)===>

实例 service.run()

resolvePkg(pkg)

通过resolvePkg(pkg)解析package.json, pkg当前命令执行所在的目录

返回值是package.json的路径

resolvePlugins

1,加载commands下的命令文件,并格式化为

[
  {
    id:'built-in:文件路径',
    apply: '命令文件'
  }
]

2,若dependencies和devDependencies中存在plugins,一并加入到当前plugins数组

判断是否有插件的规则:

id满足下面的正则表达式

/^(@vue\/|vue-|@[\w-]+(\.)?[\w-]+\/vue-)cli-plugin-/

id在this.pkg.optionalDependencies中

3,加载本地的plugins

判断是否存在:this.pkg.vuePlugins && this.pkg.vuePlugins.service

格式:

[
  {
    id: `local:${file}`,
    apply: loadModule(`./${file}`, this.pkgContext)
  }
]

run

在run中根据vue-cli-service参数 获取到对应的命令文件,执行该命令文件的函数

分析serve.js执行过程

webpack配置,通过chainWebpack引入

webpack配置文件

run方法

这里面有一个难点,就是registerCommand在哪里定义,通过分析源码可以得到,在PluginApi中中定义了方法registerCommand()方法,如图:

下面代码中的this.service指向Service实例

到这里执行命令前的逻辑基本完毕,接下来就是执行了。

猜你喜欢

转载自blog.csdn.net/qdmoment/article/details/104857781