vue-cli腳手架源碼解析(二)

前言:緊接上篇,這篇文章着重講解create.js,這是建立項目的主文件。css

從上而下,逐行解析。vue


  1. 先看依賴文件
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') // 校驗包名字,不重要
  1. 重點來看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(),他引入了好多的庫,這些庫,在用戶選擇不一樣的初始化項目的時候用獲得。node

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

真正的建立看來仍是要等到下一篇文章再說了,再重點介紹下inquirer這個庫。vue-router

inquirer命令行交互的庫,好比咱們常見的vuex

clipboard.png

一個是讓你手動輸入,y或者n,一個是選擇。typescript

clipboard.png

當全部的交互完成會,會返回一個對象,就是用戶選擇或者輸入的值,後續的輸出邏輯就依賴這個值。npm

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,用於給用戶選擇。數組

相關文章
相關標籤/搜索