我们知道,vue-cli的入口文件位置是 @vue/cli/bin/vue.js,相信你已经打开了该文件,并看到了熟悉的create命令:

NODE版本检查

在文件的开始处,有这么一段代码:


const requiredVersion = require('../package.json').engines.node

function checkNodeVersion (wanted, id) {
  if (!semver.satisfies(process.version, wanted, { includePrerelease: true })) {
    console.log(chalk.red(
      'You are using Node ' + process.version + ', but this version of ' + id +
      ' requires Node ' + wanted + '.\nPlease upgrade your Node version.'
    ))
    process.exit(1)
  }
}

checkNodeVersion(requiredVersion, '@vue/cli')

我们不难发现,这个函数用于检查node版本是否符合要求,需要注意的是requiredVersion(node版本号要求):

该字段取自 package.json中的engines对象

engines属性是键/值对的json对象,用于表示指定应用程序应在其上运行的库和运行的版本

创建

在源码中,创建命令中引用了一个方法: require('../lib/create')(name, options)

进入create.js, 就是本章的核心了:

  • path.relative   - from 到 to 的相对路径

    path.relative('/data/orandea/test/aaa', '/data/orandea/impl/bbb');
    // 返回: '../../impl/bbb'
  • validate-npm-package-name   -校验是否是正确的npm包名

 

伪代码:

function create(projectname,opts){

    校验projectname是否符合规范

    if(projectname已存在){
        if(opts.force){移除现有projectname}
        else {
            clearConsole 清空控制台并打印初始化提示信息
            if(命令=== create .){
              在当前目录下创建
            }else{
                提示用户该projectname已存在,提供【合并、替换、取消】操作
                如果是替换,则将当前目录删除
            }
        
        }
    }

    《1》创建构建实例
    《2》执行实例的创建方法

}

导出create方法并捕捉错误

clearConsole用于检测vue-cli版本更新及打印创建的提示:

根据上面的伪代码,我们找到Creator类,打开Creator.js,我懵了 😳    这,有555行代码,啊,瞬间不想看了

不想看也得看,为了诗和远方 😄

首先,大家应该对以下的截图不陌生吧,我们就从这里开始

《1》创建构建实例

就像侦探挖掘现场一样,要一步步深入,我们从伪代码《1》处开始分析,并一步步打开相关的核心文件,此时,你打开的文件如以下:

而这些文件都有什么关系呢?为了更好的理解,我画了以下UML图:

对应的关键代码如下:

vue.js

require('../lib/create')(name, options)

../lib/create.js

  const creator = new Creator(name, targetDir, getPromptModules())
  await creator.create(options)

Creator-construct

    const promptAPI = new PromptModuleAPI(this)
    promptModules.forEach(m => m(promptAPI))

PromptModuleAPI.js

module.exports = class PromptModuleAPI {
  constructor (creator) {
    this.creator = creator
  }

  injectFeature (feature) {
    this.creator.featurePrompt.choices.push(feature)
  }

  injectPrompt (prompt) {
    this.creator.injectedPrompts.push(prompt)
  }

  injectOptionForPrompt (name, option) {
    this.creator.injectedPrompts.find(f => {
      return f.name === name
    }).choices.push(option)
  }

  onPromptComplete (cb) {
    this.creator.promptCompleteCbs.push(cb)
  }
}

@vue/cli/lib/util/createTools.js

exports.getPromptModules = () => {
  return [
    'vueVersion',
    'babel',
    'typescript',
    'pwa',
    'router',
    'vuex',
    'cssPreprocessors',
    'linter',
    'unit',
    'e2e'
  ].map(file => require(`../promptModules/${file}`))
}

e2e.js

module.exports = cli => {
  cli.injectFeature({
    name: 'E2E Testing',
    value: 'e2e',
    short: 'E2E',
    description: 'Add an End-to-End testing solution to the app like Cypress or Nightwatch',
    link: 'https://github.com/vuejs/vue-cli/tree/dev/docs#e2e-testing',
    plugins: ['e2e-cypress', 'e2e-nightwatch', 'e2e-webdriverio']
  })

  cli.injectPrompt({
    name: 'e2e',
    when: answers => answers.features.includes('e2e'),
    type: 'list',
    message: 'Pick an E2E testing solution:',
    choices: [
      {
        name: 'Cypress (Test in Chrome, Firefox, MS Edge, and Electron)',
        value: 'cypress',
        short: 'Cypress'
      }
    ]
  })

  cli.injectPrompt({
    name: 'webdrivers',
    when: answers => ['nightwatch', 'webdriverio'].includes(answers.e2e),
    type: `checkbox`,
    message: `Pick browsers to run end-to-end test on`,
    choices: [
      {
        name: `Chrome`,
        value: 'chrome',
        checked: true
      },
      {
        name: 'Firefox',
        value: 'firefox',
        // check the "Firefox" option if user has installed it
        checked: !!installedBrowsers.firefox
      }
    ]
  })

  cli.onPromptComplete((answers, options) => {
  })
}

以上几个文件环环相扣,就为了做成一件事,那就是:处理初始化的插件提示及预置选项 

由此我们结束了对Creator构造函数中的执行动作的挖掘 😄

《2》执行实例的创建方法

我们来到Creator.js文件中,将目光移向真正重要的create方法,滚动条缓缓往下拉,缓缓往下拉,往下拉,往下,!!!!!!!居然这么多的嘛!!!!!!!🤮

收起代码发现这个方法有200+行,啊,道阻且难,我长叹一口气,算了,明天再看吧 😋

 

 

Logo

前往低代码交流专区

更多推荐