寫於 2017.10.20
相信對於大部分使用過VueJS的同學來說,vue-cli
是他們非常熟悉的一個工具。藉助vue-cli
,我們通過非常簡單的問答形式,方便地初始化一個vue工程,完全不需要擔心繁複的webpack、eslint配置等等。
但是,仍然有許多同學沒有搞清楚vue-cli
和vue工程
之間的關係,導致沒有充分發揮vue-cli
的功能。在這篇文章中,我將從底層原理開始並結合幾個例子,告訴大家vue-cli
還能這樣用。
什麼是vue-cli
引用vue-cli官方文件的一句話:
A simple CLI for scaffolding Vue.js projects. 一個簡單的Vue.js工程命令列腳手架工具。
在全域性安裝vue-cli之後,就可以通過一條命令初始化我們的vue工程:
vue init <template-name> <project-name>
複製程式碼
接下來vue-cli就會按照這個<template-name>
模板內部的設定,丟擲幾個問答選項。在回答完問答選項以後,我們的vue工程目錄就已經生成好了,接下來只要把依賴安裝完,直接就可以跑起來,是不是非常方便呢?
接下來,我們就要看看,這一條命令的背後,究竟發生了一些什麼事。
vue-cli初始化專案的原理
從官方文件可以知道,vue-cli使用了download-git-repo這個工具去下載遠端git倉庫裡面的工程,如果加上了--clone
引數,則會在內部執行git clone
,通過克隆的方式把遠端git倉庫拉取到本地。明白這一點至關重要:
vue-cli並非從無到有地憑空生成一個專案,而是通過下載/拉取已有的工程到本地,完成生成專案的工作。
而這個“已有的工程”,就是所謂的“模板(template)”。
當然,vue-cli可不只是把模板拉取到本地這麼簡單,它還允許我們通過問答的形式對模板進行個性化配置,這個又是如何做到的呢?
vue-cli使用了inquirer.js實現了“問答環節”,簡單來說是這樣子的:
// 準備幾個問題
const questions = [
{
type: 'input',
name: 'name',
message: 'What's your name?'
},
{
type: 'input',
name: 'age',
message: 'How old are you?',
}
]
複製程式碼
然後把這段問題傳給inquirer.js就可以了:
inquirer.prompt(questions).then(({ name, age }) => {
console.log(`My name is ${name}, and I'm ${age} years old`)
})
複製程式碼
在執行的時候,vue-cli會在命令列裡面把What's your name?
和How old are you?
這兩個問題相繼丟擲,獲取使用者輸入,把輸入賦值給name
和age
變數,這樣就能夠獲取使用者的輸入資訊了。接著我們引出下一個問題,這些使用者輸入,是如何跟模板的自定義關聯起來的呢?
我們開啟一個vue-cli的模板,比如webpack-simple裡面的README.md,它長這樣:
# {{ name }}
> {{ description }}
複製程式碼
上面使用雙括號包裹起來的,最終會根據使用者的輸入而更改為具體的內容。是不是覺得這種寫法很熟悉?其實就是Handlebars的模板語法。
以這個README.md檔案為例,在vue-cli執行的過程中,會首先讀取檔案的內容放在記憶體,然後通過inquirer.js
獲取使用者輸入,把輸入的值替換到檔案內容裡面,最後通過另外一個名叫Metalsmith的工具,把替換好的內容輸出為檔案,也就生成了具有個性化內容的README.md檔案了。
整個流程並不複雜,在明白這些原理後,我們就能更深入地使用vue-cli了。
Javascript與Java,Vue-cli與Vue
雖然這麼類比不太準確,但我想大家也應該能明白我的意思。
簡單來說,就是vue-cli不僅僅能初始化vue工程,理論上能夠初始化一切工程,包括react,angular等等等等,只要你有一份能夠執行的模板,就能夠通過vue-cli進行工程的初始化。
在討論區有許多類似的問題:
- “vue-cli當中如何配置sass?”
- “vue-cli中如何修改devServer的埠?”
- “vue-cli中發現專案跑不起來”
- ……
vue-cli說:“這鍋我不背。”
是的,所遇到的問題都不是vue-cli的問題,而是相關模板的問題。那麼應該如何寫一份合格的模板呢?下面我們一起來研究一下。
寫一份vue-cli模板
參考官方文件,也許還是不能理解到底應該怎麼寫,那麼我們可以直接參考官方例子webpack-simple,看看它到底是怎麼寫的。
首先可以看到目錄結構:
著實是非常簡單,其中meta.json
就是向使用者丟擲的問答題,/template
目錄則是真正的模板內容。首先我們來看看meta.json
都寫了些啥:
{
"prompts": {
"name": {
"type": "string",
"required": true,
"label": "Project name"
},
"description": {
"type": "string",
"required": true,
"label": "Project description",
"default": "A Vue.js project"
},
"author": {
"type": "string",
"label": "Author"
},
"sass": {
"type": "confirm",
"message": "Use sass?",
"default": false
}
},
"completeMessage": "{{#inPlace}}To get started:\n\n npm install\n npm run dev.{{else}}To get started:\n\n cd {{destDirName}}\n npm install\n npm run dev.{{/inPlace}}"
}
複製程式碼
可以看到,它一共向使用者提了4個問題:
- Project name
- Project description
- Author
- Use sass?
接著,我們開啟/template
目錄,看看它長什麼樣:
這就是終將被生成的工程目錄。開啟裡面的package.json
:
{
"name": "{{ name }}",
"description": "{{ description }}",
"version": "1.0.0",
"author": "{{ author }}",
"private": true,
"scripts": {
"dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot",
"build": "cross-env NODE_ENV=production webpack --progress --hide-modules"
},
"dependencies": {
"vue": "^2.4.4"
},
"devDependencies": {
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-preset-env": "^1.6.0",
"cross-env": "^5.0.5",
"css-loader": "^0.28.7",
"file-loader": "^1.1.4",
{{#sass}}
"node-sass": "^4.5.3",
"sass-loader": "^6.0.6",
{{/sass}}
"vue-loader": "^13.0.5",
"vue-template-compiler": "^2.4.4",
"webpack": "^3.6.0",
"webpack-dev-server": "^2.9.1"
}
}
複製程式碼
結合前文原理裡面的內容,也不難理解這個package.json
裡面雙括號的含義了。
看到這裡,是不是已經躍躍欲試,想要寫一份屬於自己的模板呢?又或者想要打造一款屬於自己的命令列腳手架工具?原理都是很簡單的,只要按照想法一步步實現即可。
後記
其實在去年早些時候,已經寫了兩篇腳手架相關的文章:
但是發現仍然有許多同學對於vue-cli的理解有些偏差,於是寫下這篇文章,聊一聊自己的理解。
By the way,我將會在11月16日晚上8點,在Segmentfault開展live講座,主題是《【前端工程化】:玩轉Webpack配置》,歡迎感興趣的同學報名參加哦,保證精心準備,乾貨滿滿!
報名連結:segmentfault.com/l/150000001…
期待和大家的分享交流~