vite不能選配方案?vite-creater強勢來襲!
我正在參加「掘金·啟航計劃」
項目背景
vite出現之后,迅速帶走了一大波webpack的使用者,即使是對打包工具不熟悉的小白,也能很快感受到兩者的區別——vite快的多!
vite官方文檔第一句也是講述其名字的由來 Vite (法語意為 "快速的") ,其logo也與其名字一樣,處處都透露著一個字,那就是快!
但是習慣了vue-cli的同學(我),對于一個不能保存模板策略的工具,是無法忍受的,它居然每次都需要我選擇模板、選擇用js還是ts,這是讓人無法忍受的。當然,vite官方還提供了社區維護的模板 即
awesome-vite ,同學可點擊鏈接感受一下這些模板,不能說我們小白用不到吧,可以說是完全不認識。
為此,"好東西" vite-creater 誕生了 github源碼 ?? 點擊走你
什么是vite-creater?
vite-creater是vite的一個前置的自動化cli程序,它可以按照用戶自定義的流程全自動的創建項目,并安裝依賴,當vite-creater提示完成時,你就可以直接npm run了!它調用的是npm create vite,除了選擇框架外,其余的一切操作都不需要你動手,你只需預設一個策略即可!
我需要vite-creater嗎?
如果你是一個熟練的vue玩家,我猜你可能需要它,它可以像vue-cli一樣,儲存一個自己的選配策略,它甚至支持你包含自定義的第三方庫。
如果你還不了解vite,或者你希望使用vite原汁原味的功能,你可能不需要vite-creater,不過歡迎你使用,vite-creater會隨著vite的更新而更新!
使用vite-creater
安裝vite-creater
npm i vite-creater -g
快速開始
vcreater init <yourProjectName>
vite-creater內置了一個貼心的選配策略:

這也是目前應用最多的,開發起來最容易的一套策略,在此直接回車,你會直接一鍵生成項目

如果你不喜歡,或者你需要更多的東西,可以點擊 "點擊進入自定義流程"
自定義選配
vite-creater會問詢一系列常用套件,包括:css預處理器、使用js還是ts、是否使用vue-router、使用vuex還是pinia
(vite-creater目前版本只支持 問詢vue常用包,如需其他框架,可以全選擇no,然后在自定義第三方包中添加你的框架需要的包即可)
最后,vite-creater會問你,是否需要其他的第三方包,比如我們需要使用 超好用的大屏自適應工具 vue-autofit ,我們就輸入vue-autofit

最后,可以選擇將此選配方案保存,你可以選擇給它取一個名字,當然也可以不取,因為vite-creater會在預設方案列表中展示所有依賴名稱和使用的語言。
如果vite-creater要求你選擇框架,你可以根據自己的需要選擇你的框架:
當選擇完框架后,即可快速完成項目創建了!并且已經下載了你的自定義包。


使用保存的選配方案

當你創建過一個方案并選擇了保存后,工具會在下次使用時向你展示你保存的選配方案,直接選擇即可一鍵生成項目,不用再重復選配過程。
vite-creater是怎么實現的?
vite-creater是node編寫的。
調用Node編寫的cli程序,必須在node環境下才可以運行,因為node的cli實際上是由node代理執行的,即V8引擎去解析和執行的,當我們全局安裝了一個node cli程序時,node會自動把其命令加載到環境變量中,當我們的JS代碼被執行時,是node在與操作系統交互。所以,我們不需要了解它具體的運行原理,我們只需要知道JS怎么寫就可以了。
開發所需的庫
"commander": "^10.0.1" 可以執行dos命令
"inquirer": "^9.2.0" 交互式輸出工具,提供問詢式命令行交互會用到
"configstore": "^6.0.0" 本地存儲,相當于是cookie或者localStorage,用來儲存用戶保存的選配
開發步驟
使用npm 初始化項目
npm init
需要輸入項目基本信息,此步驟會初始化一個標準的Npm包,并生成一個package.json ,
注意如果希望發布到npm,應該先在npm官網查看是否有相同或相似的包名,有的話是發布不了的,需要取一個標新立異的包名,或者就需要帶上@userName/的前綴
使用commander庫初始化命令
import { program } from 'commander';
program
.version('1.0.0')
.description(`vite-creater是一款用于快速創建vite項目的腳手架工具`);
program
.command('init <projectName>')
.description('使用vite-creater創建項目')
.option('-p, --projectName <string>', 'project name')
.action(async (initProjectName) => {
await askForOptions(initProjectName) //這里調用我們的自定義問詢函數
});
program.parse(process.argv);
在node開發的cli中,可以使用async/await來阻塞程序,以等待步驟完成或者用戶輸入。
使用inquirer創建交互式問詢輸出
import inquirer from 'inquirer';
let preSetRules = [
{
name: 'selectRule',
type: 'list',
message: '選擇一個預設規則,或者進入自定義流程',
choices: preSetRulesList, //這是一個數組,僅可包含字符串,如["item1","item2"]
}
]
let isPreSetRules = await inquirer.prompt(preSetRules)
當如上代碼被執行時,將會輸出一個可以通過上下箭頭鍵選擇的列表(list)
使用configstore 儲存用戶的選配方案
import Configstore from 'configstore';
const conf = new Configstore('vite-creater');
conf.set("customRulesList", customRulesList); //新建或修改 參數:鍵名,數據
let customRulesList = conf.get('customRulesList');
其中customRulesList 可以是數組或者對象,當然也可以是字符串等,你可以把configstore 完全當作cookie來使用。
使用child_process創建子進程
這是一個node內置的庫,允許開發者創建一個子進程,并與子進程通訊
import { exec } from 'child_process';
function execCreateTs(command) {
console.log('exec:', command);
return new Promise((resolve, reject) => {
const child = exec(command, (err, stdout, stderr) => {
if (err) {
console.log('err::: ', err);
reject(err)
}
})
child.stdout.on('data', async data => { //監聽子進程的輸出
if (data.includes('Package name')) {
process.stdout.write('\x1b[32m' + data + '\x1b[0m');
child.stdin.write('\n');
}
if (data.includes('Vue')) {
process.stdout.write('\x1b[2J\x1b[0f');
process.stdout.write('\x1b[32m' + data + '\x1b[0m');
clearAnimation()
selectFramework(child)
}
if (data.includes('TypeScript')) {
process.stdout.write('\x1b[32m' + data + '\x1b[0m');
process.stdout.write('\x1b[2J\x1b[0f');
child.stdin.write('\n');
resolve(child.stdout)
}
if (data.includes('is not empty')) {
// 退出進程
console.log('\n\x1b[31m×\x1b[0m 目錄已存在');
process.exit();
}
})
})
}
上述代碼由vite-creater創建ts項目為例,參數command即可以是任何dos命令。下面的if來查詢子進程的輸出中包含的字符,以此來確定子進程進行到哪一步了(我不知道這么做是不是符合規范的,不過開發的時候我想到了這個辦法。)
細心的同學注意到了selectFramework()方法,這個方法是在子進程中出現了Vue字符時,我們判定vite進入了框架選擇步驟,于是我們將子進程的輸出展示到主進程中,也就是上面提到的框架選擇頁面
selectFramework方法代碼如下:
async function waitUserPresskey() {
// 返回一個promise對象
return await new Promise((resolve, reject) => {
process.stdin.setRawMode(true);
process.stdin.resume();
process.stdin.on('data', (key) => {
key = key.toString('ascii'); //需要轉為ascii碼
resolve(key)
});
});
}
async function selectFramework(child) {
let input = await waitUserPresskey();
// 如果按下ctrl+c,退出進程
if (input === '\u0003') {
process.exit();
}
child.stdin.write(input); // 向子進程轉發命令
}
當調用它時,程序會等待一個用戶輸入,然后直接轉發到子進程中,當子進程再次輸出其他信息時,又會回到我們上面的監聽,于是,只要用戶還沒有選定框架,vite會一直處在框架選擇頁面,也就是還包含Vue字符,所以會再次進入selectFramework函數,這樣就完成了一個遞歸問詢,直到用戶選擇了框架。
全自動化流程實現
當完成上述步驟之后,我們已經可以看到vite+vue的項目已經創建完成了,這時就已經完成了vite官方工具所做的,一般來說,我們需要進入該文件夾,然后執行npm i ,然后安裝我們需要的包 npm i ....
根據上面的學習,我們理所當然的可以將這一步收納進自動化的范疇,只需執行兩條簡單的dos命令即可。
await execNpmInstall('npm i')
await execNpmInstall(installCommand)
function execNpmInstall(command) {
console.log('exec:', command);
return new Promise((resolve, reject) => {
const child = exec(command, (err, stdout, stderr) => {
if (err) {
reject(err)
}
})
child.stdout.on('data', async data => {
// 當npm i 完成時
if (data.includes('packages in')) {
console.log('\n', data);
resolve(child.stdout)
}
})
})
}
如果我們需要安裝 之前用戶儲存的第三方庫,只需要使用使用conf.get('xxx');去獲取數據,然后傳入該函數即可。
完成
上面簡述了vite-creater的開發過程,至此,我們就可以整理所有的功能,打包發布了,在本地登錄自己的npm賬號后,使用npm publish命令即可發布。
本項目已在 github開源 github源碼 ?? 點擊走你
結語
懦弱之舉,我決不姑息!

浙公網安備 33010602011771號