[Vue CLI 3] 源碼系列之init

用慣老版本 Vue CLI 的同學(xué)一般多會(huì)選擇使用如下命令來創(chuàng)建模板項(xiàng)目:

vue init webpack demo

但是在新版中,推薦使用 vue create赃阀,官方也提到了:

因?yàn)槭褂昧送瑯右粋€(gè) vue 命令晒屎,所以之前的會(huì)被覆蓋佑附,如果還需要使用搞乏,需要自行安裝:

npm install -g @vue/cli-init

我們先看一下邻眷,如果本地已經(jīng)安裝了最新版本的 Vue CLI眠屎,執(zhí)行之前的 vue init 會(huì)出現(xiàn)什么?

命令行會(huì)提示你如下內(nèi)容:

Command vue init requires a global addon to be installed.

Please run npm install -g @vue/cli-init and try again.

那它背后的設(shè)計(jì)是如何的呢耗溜?

1组力、首先還是 vue 的一個(gè)擴(kuò)展命令:

我們還是找到 @vue/cli/bin/vue.js,我們發(fā)現(xiàn)如下代碼:

之前我們也提到過抖拴,命令行最核心的基礎(chǔ)包是:commander

const program = require('commander')

這里配置了 command、description腥椒、option 和 action

program

.command('init <template> <app-name>')

.description('generate a project from a remote template (legacy API, requires @vue/cli-init)')

.option('-c, --clone', 'Use git clone when fetching remote template')

.option('--offline', 'Use cached template')

.action(() => {

loadCommand('init', '@vue/cli-init')

})

然后調(diào)用了 loadCommand阿宅,傳入了 2 個(gè)參數(shù),我們看一下 @vue/cli/lib/util/loadCommand

文件對(duì)外暴露一個(gè) loadCommand 函數(shù)笼蛛,接受 2 個(gè)參數(shù)

module.exports = function loadCommand (commandName, moduleName) {

// ...

}

內(nèi)部會(huì)通過 try catch 加載對(duì)應(yīng)的第二個(gè)參數(shù) moduleName洒放,這里為 @vue/cli-init

try {
return require(moduleName);
}

這里因?yàn)槲覀儽镜貨]有,會(huì)報(bào)錯(cuò)進(jìn)入 catch:

Error: Cannot find module '@vue/cli-init'

我們看一下 catch 的處理:

因?yàn)橛?2 個(gè)地方會(huì)判斷 err 所以復(fù)用了一個(gè)函數(shù): isNotFoundError

const isNotFoundError = err => {
return err.message.match(/Cannot find module/)
}

注意這里有一個(gè)策略滨砍,在判斷沒有之后往湿,會(huì)再次 try catch 到全局里面看

catch (err) {
if (isNotFoundError(err)) {
//...
} else {
throw err
}
}

代碼實(shí)現(xiàn)如下妖异,用來一個(gè)工具包:import-global

try {
return require('import-global')(moduleName)
}

如果再失敗,就只能出提示了领追,就是上面一開始我們看到的:

這里用了工具包 chalk 來給文字做樣式他膳,同時(shí)還有一個(gè)有用的:

會(huì)判斷你是否安裝了yarn,如果有绒窑,就推薦你用它來全局安裝 @vue/cli-init

判斷函數(shù)來自我們之前 config 一直打交道的 @vue/cli-shared-utils

函數(shù)名 hasYarn

const { hasYarn } = require('@vue/cli-shared-utils')

我們看一下具體實(shí)現(xiàn):源碼在 @vue/cli-shared-utils/lib/env.js

外層有一個(gè)變量: _hasYarn

let _hasYarn

函數(shù)結(jié)構(gòu):

exports.hasYarn = () => {

}

會(huì)做幾層判斷:

先看這個(gè) env 變量

if (process.env.VUE_CLI_TEST) {
return true
}

然后再看那個(gè)變量棕孙,有值就直接返回

if (_hasYarn != null) {
return _hasYarn
}

最核心的來了:

使用核心模塊 child_process

const { execSync } = require('child_process')

執(zhí)行 yarnpkg 命令

execSync('yarnpkg --version', { stdio: 'ignore' })

然后分別給變量賦值,有就是 true些膨,否則是 false

------------------------------- 分割線 ----

我們參照建議蟀俊,全局安裝之后,我們查看 @vue/cli-init/index.js

代碼一共這么多行:作者在 readme 也提示的很清晰

This is simply an alias to the old vue-cli@2.x.

核心是使用 execa 工具包订雾,執(zhí)行老版本的 vue-cli/bin/vue-init肢预,傳入了命令行上面的參數(shù)(這里沒有用工具包)

const execa = require('execa')
const binPath = require.resolve('vue-cli/bin/vue-init')
execa(
binPath,
process.argv.slice(process.argv.indexOf('init') + 1),
{ stdio: 'inherit' }
)

我們看一下在命令行輸入:vue init webpack demo 之后,process.argv 是什么洼哎?

[ '/usr/local/bin/node','/usr/local/bin/vue',
'init',
'webpack',
'demo' ]

process.argv.indexOf('init') + 1 返回的是:

3

process.argv.slice(3) 返回的是:

[ 'webpack', 'demo' ]

------ 分割線 -----

本文來自微信公眾號(hào):[前端新視野]的原創(chuàng)文章

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末误甚,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子谱净,更是在濱河造成了極大的恐慌窑邦,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,607評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件壕探,死亡現(xiàn)場離奇詭異冈钦,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)李请,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門瞧筛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人导盅,你說我怎么就攤上這事较幌。” “怎么了白翻?”我有些...
    開封第一講書人閱讀 164,960評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵乍炉,是天一觀的道長。 經(jīng)常有香客問我滤馍,道長岛琼,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,750評(píng)論 1 294
  • 正文 為了忘掉前任巢株,我火速辦了婚禮槐瑞,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘阁苞。我一直安慰自己困檩,他們只是感情好祠挫,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,764評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著悼沿,像睡著了一般等舔。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上显沈,一...
    開封第一講書人閱讀 51,604評(píng)論 1 305
  • 那天软瞎,我揣著相機(jī)與錄音,去河邊找鬼拉讯。 笑死涤浇,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的魔慷。 我是一名探鬼主播只锭,決...
    沈念sama閱讀 40,347評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼院尔!你這毒婦竟也來了蜻展?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,253評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤邀摆,失蹤者是張志新(化名)和其女友劉穎纵顾,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體栋盹,經(jīng)...
    沈念sama閱讀 45,702評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡施逾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,893評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了例获。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片汉额。...
    茶點(diǎn)故事閱讀 40,015評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖榨汤,靈堂內(nèi)的尸體忽然破棺而出蠕搜,到底是詐尸還是另有隱情,我是刑警寧澤收壕,帶...
    沈念sama閱讀 35,734評(píng)論 5 346
  • 正文 年R本政府宣布妓灌,位于F島的核電站,受9級(jí)特大地震影響啼器,放射性物質(zhì)發(fā)生泄漏旬渠。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,352評(píng)論 3 330
  • 文/蒙蒙 一端壳、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧枪蘑,春花似錦损谦、人聲如沸岖免。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽颅湘。三九已至,卻和暖如春栗精,著一層夾襖步出監(jiān)牢的瞬間闯参,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評(píng)論 1 270
  • 我被黑心中介騙來泰國打工悲立, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留鹿寨,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,216評(píng)論 3 371
  • 正文 我出身青樓薪夕,卻偏偏與公主長得像脚草,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子原献,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,969評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容