做爲一個菜鳥,我有一顆好奇的心,每當vue init 的時候,看到那流暢的進度和神奇的結果,內心都充滿一窺其本質的指望……前端
如下就是我不斷的console,大體理出來的一個流程心得,紀錄在此,以做備忘。vue
一、which vue,定位vue命令的實際位置node
二、去往命令vue的目錄,查看代碼webpack
這裏的commander包是用來建立命令行的工具,其npm官網粗略瞭解,瞭解到其中的init、list命令會在當前目錄尋找執行vue-init、vue-list文件git
The commander will try to search the executables in the directory of the entry script (like
./examples/pm
) with the nameprogram-command
, likepm-install
,pm-search
.es6
三、查看vue-init文件及其代碼github
經過ls命令咱們能夠看到,命令文件的真實位置是在全局node_modules下的vue-cli裏面,因此代碼裏的require包都是從vue-cli包下找的web
這個文件就是init命令的主體了,裏面主要有vue-cli
download-git-repo、inquirer等包 和 cli/lib下的功能函數 check-version、generate等
3.一、check-version 的做用npm
首先其會比對vue-cli的package.json裏的node版本和當前process.version的環境版本,若是環境版本低就會報錯。
其次其會請求線上vue-cli的最新版本,來告訴用戶是否有新的vue-cli版本能夠更新,只是給用戶一個提示
const request = require('request') const semver = require('semver') const chalk = require('chalk') const packageConfig = require('../package.json') module.exports = done => { // Ensure minimum supported node version is used if (!semver.satisfies(process.version, packageConfig.engines.node)) { return console.log(chalk.red( ' You must upgrade node to >=' + packageConfig.engines.node + '.x to use vue-cli' )) } request({ url: 'https://registry.npmjs.org/vue-cli', timeout: 1000 }, (err, res, body) => { if (!err && res.statusCode === 200) { const latestVersion = JSON.parse(body)['dist-tags'].latest const localVersion = packageConfig.version if (semver.lt(localVersion, latestVersion)) { console.log(chalk.yellow(' A newer version of vue-cli is available.')) console.log() console.log(' latest: ' + chalk.green(latestVersion)) console.log(' installed: ' + chalk.red(localVersion)) console.log() } } done() }) }
3.2 、download-git-repo的做用
用來經過git clone 或者 http下載的方式,從github、gitlab等平臺下載倉庫代碼,具體可去官網查看,
默認,咱們沒有指定clone參數,程序會從 https://github.com/vuejs-templates/webpack/archive/master.zip 下載模版
若是用 vue init webpack -c 則會經過 git clone git@github.com:vuejs-templates/webpack.git 來下載(本地配置sshkey,能夠下載私有庫)
tmp變量是臨時存放模版的目錄,默認在 ~/.vue-templates/
const tmp = path.join(home, '.vue-templates', template.replace(/[\/:]/g, '-')) …… download(template, tmp, { clone }, err => { spinner.stop() if (err) logger.fatal('Failed to download repo ' + template + ': ' + err.message.trim()) generate(name, tmp, to, err => { if (err) logger.fatal(err) logger.success('Generated "%s".', name) }) })
若是咱們要配置本身項目的模版目錄,就好好看看vue-init文件裏的run函數吧 ^_^,祝你成功^_^。
3.三、inquirer的做用
起到一個prompt confirm的做用
Generate project in current directory?
Target directory exists. Continue?
3.四、generate函數的做用
主要代碼
metalsmith.clean(false) .source('.') // start from template root instead of `./src` which is Metalsmith's default for `source` .destination(dest) .build((err, files) => { done(err) if (typeof opts.complete === 'function') { const helpers = { chalk, logger, files } opts.complete(data, helpers) } else { logMessage(opts.completeMessage, data) } })
下載完模版後的處理邏輯都在這裏面了,函數文件位於 vue-cli/lib/generate.js,這裏面主要用了
metalsmith、handlebars等包 和 lib/options.js
options.js 會去 ~/.vue-templates/模版 目錄下獲取 meta.js 或者 meta.json 中的配置。
這個配置就是用來配置圖中的東西。
3.4.一、metalsmith 的做用
相似於gulp,是一個流程工具,英文很差,我看它看的頭疼,只知道它幹了什麼,但不知道它是怎麼作的。
它會配置options.js裏獲取的配置數據,對模版文件進行過濾
3.4.二、handlebars 的做用
一個js模版工具,相似服務端的smarty、前端的artemplate、es6的字符串模版等。
它會在metalsmith的流程裏處理模版裏的變量,把咱們填寫的項目名等數據渲染成最終的文件,寫進當前項目目錄裏。《完》
好久沒寫博客,寫着好彆扭啊,不支持markdown,只能憑感受來寫了,估計預覽起來會很難看,但願你們見諒。
最後吟詩一首:
「衆鳥高飛盡,孤雲獨去閒。相看兩不厭,只有敬亭山。」