vite插件打包更順暢使用技巧示例
前言
在上一篇給大家?guī)砹恕?a href="http://www.dhdzp.com/article/252603.htm" rel="external nofollow" target="_blank">如何入門去寫一個 vite 插件》,能看的出來同學(xué)們也甚是喜歡,如果大家對 vite 感興趣,可以關(guān)注我的專欄《vite 從入門到精通》;
因為公司目前大部分項目都已轉(zhuǎn)為 vite,為了給社區(qū)添加一份貢獻(xiàn),故開發(fā)了一個已經(jīng)應(yīng)用到項目中的vite 前端打包進(jìn)度條 的插件 vite-plugin-progress;
介紹
vite-plugin-progress 插件是一個在打包時展示進(jìn)度條的插件,如果您覺得該插件對您的項目有幫助,歡迎 star ?? 支持一下,感謝!

用法
安裝
# npm npm i vite-plugin-progress -D # yarn yarn add vite-plugin-progress -D # pnpm pnpm i vite-plugin-progress -D
使用(不帶參數(shù)):在 vite.config.js / vite.config.ts 中配置
import progress from 'vite-plugin-progress'
export default {
plugins: [
progress()
]
}
參數(shù) 0ptions:
- format :自定義進(jìn)度條的格式;
- width :進(jìn)度條在終端中的寬度;
- complete :完成后的默認(rèn)字符 \u2588 ;
- incomplete :未完成的默認(rèn)字符 \u2591 ;
- renderThrottle :間隔更新時間默認(rèn)16(毫秒);
- clear :完成后是否清除終端,默認(rèn) false;
- callback :完成后執(zhí)行的回調(diào)函數(shù);
- stream 終端中的輸出格式流,默認(rèn) stderr ;
- head :進(jìn)度條的頭字符;
參數(shù) options 中的 format 中各個標(biāo)記含義:
- :bar :代表進(jìn)度條;
- :current :當(dāng)前執(zhí)行到哪的刻度;
- :total :總刻度;
- :elapsed :所用時間(秒);
- :percent :完成的百分比;
- :eta :預(yù)計完成時間(秒);
- :rate :每一秒的速率;
使用(帶參數(shù)):
// vite.config.js / vite.config.ts
import progress from 'vite-plugin-progress'
export default {
plugins: [
progress({
format: 'building [:bar] :percent',
total: 200,
width: 60,
complete: '=',
incomplete: '',
})
]
}
給自定義進(jìn)度條加點顏色:
安裝 picocolors :
pnpm i picocolors -D
使用:
// vite.config.js / vite.config.ts
import progress from 'vite-plugin-progress'
import colors from 'picocolors'
export default {
plugins: [
progress({
format: `${colors.green(colors.bold('Bouilding'))} ${colors.cyan('[:bar]')} :percent`
})
]
}
如果您只想使用該插件的話,那么現(xiàn)在就去安裝使用吧!
如果您對實現(xiàn)思路感興趣的話,那么您可以繼續(xù)向下滾動查閱喲 ~
實現(xiàn)思路
其實實現(xiàn)這個功能,我們最主要的考慮就是當(dāng)前 vite 打包的進(jìn)度到哪里了,那么我們思考兩個問題:
- 考量當(dāng)前 vite 打包的進(jìn)度是到哪里了?
- 如何知道當(dāng)前打包的進(jìn)度?
熟悉 webpack 的朋友,肯定對 webpack 的打包進(jìn)度條也不陌生;會發(fā)現(xiàn)在 webpack 中,webpack 暴露了一個 webpack.ProgressPlugin 的事件鉤子,這樣就導(dǎo)致在 webpack 中實現(xiàn)進(jìn)度條會很容易,直接通過該鉤子去封裝即可;
但是在 vite 中由于是基于 Rollup 來構(gòu)建打包代碼,所以我們是沒法知道當(dāng)前 vite 打包進(jìn)度的;
借用 vite 其中某位作者的原話:

簡單理解意思就是說在 vite 打包時,是沒法知道進(jìn)度條的 0%-100%,因為您必須先確定要構(gòu)建的模塊的總數(shù)
雖然我們不知道模塊總數(shù),但是我們可以在第一次打包時模擬一個;
并且在第一次打包的時候,我們 記錄下對應(yīng)的模塊數(shù)量,然后 緩存起來,這樣我們不就可以知道對應(yīng)的模塊數(shù)量了嗎?
說干就干 ~
第一次打包(模擬模塊總數(shù))
因為我們可以知道 src 目錄 下所有的文件總數(shù),所以就可以假設(shè)在第一次打包時用該總數(shù)來代替模塊總數(shù);
那么簡單公式:進(jìn)度條百分比 = 當(dāng)前轉(zhuǎn)換的模塊 / 模擬的模塊總數(shù)
import type { PluginOption } from 'vite';
import rd from 'rd';
export default function viteProgressBar(options?: PluginOptions): PluginOption {
// 文件類型總數(shù)
let fileCount = 0
let transformCount = 0
let transformed = 0 // 當(dāng)前已轉(zhuǎn)換的數(shù)量
retun {
...
config(config, { command }) {
if (command === 'build') {
const readDir = rd.readSync('src');
const reg = /\.(vue|ts|js|jsx|tsx|css|scss||sass|styl|less)$/gi;
readDir.forEach((item) => reg.test(item) && fileCount++);
}
},
transform(code, id) {
transformCount++
const reg = /node_modules/gi;
if (!reg.test(id){
percent = +(transformed / fileCount).toFixed(2)
}
}
}
}
與進(jìn)度條配合
那么既然我們已經(jīng)算出了基本的進(jìn)度條,也知道了基本思路,那么我們就把進(jìn)度條加進(jìn)去
import type { PluginOption } from 'vite';
import progress from 'progress';
import rd from 'rd';
export default function viteProgressBar(options?: PluginOptions): PluginOption {
let fileCount = 0 // 文件類型總數(shù)
let transformCount = 0 // 轉(zhuǎn)換的模塊總數(shù)
let transformed = 0 // 當(dāng)前已轉(zhuǎn)換的數(shù)量
let lastPercent = 0; // 記錄上一次進(jìn)度條百分比
const bar: progress;
retun {
...
config(config, { command }) {
if (command === 'build') {
// 初始化進(jìn)度條
options = {
width: 40,
complete: '\u2588',
incomplete: '\u2591',
...options
};
options.total = options?.total || 100;
const transforming = isExists ? `${colors.magenta('Transforms:')} :transformCur/:transformTotal | ` : ''
const chunks = isExists ? `${colors.magenta('Chunks:')} :chunkCur/:chunkTotal | ` : ''
const barText = `${colors.cyan(`[:bar]`)}`
const barFormat =
options.format ||
`${colors.green('Bouilding')} ${barText} :percent | ${transforming}${chunks}Time: :elapseds`
delete options.format;
bar = new progress(barFormat, options as ProgressBar.ProgressBarOptions);
// 統(tǒng)計目錄下的文件總數(shù)
const readDir = rd.readSync('src');
const reg = /\.(vue|ts|js|jsx|tsx|css|scss||sass|styl|less)$/gi;
readDir.forEach((item) => reg.test(item) && fileCount++);
}
},
transform(code, id) {
transformCount++
const reg = /node_modules/gi;
if (!reg.test(id){
lastPercent = percent = +(transformed / fileCount).toFixed(2)
}
// 更新進(jìn)度條
bar.update(lastPercent, {
transformTotal: cacheTransformCount,
transformCur: transformCount,
chunkTotal: cacheChunkCount,
chunkCur: 0,
})
},
closeBundle() {
// close progress
bar.update(1)
bar.terminate()
}
}
}
添加緩存
為了更準(zhǔn)確的知道打包的進(jìn)度,那么我們在第一次模擬了總數(shù)的時候,也要同時把真實的模塊總數(shù)給緩存起來,這樣在下一次打包時才能更加準(zhǔn)確的計算出進(jìn)度條;
新增緩存文件 cache.ts
import fs from 'fs';
import path from 'path';
const dirPath = path.join(process.cwd(), 'node_modules', '.progress');
const filePath = path.join(dirPath, 'index.json');
export interface ICacheData {
/**
* 轉(zhuǎn)換的模塊總數(shù)
*/
cacheTransformCount: number;
/**
* chunk 的總數(shù)
*/
cacheChunkCount: number
}
/**
* 判斷是否有緩存
* @return boolean
*/
export const isExists = fs.existsSync(filePath) || false;
/**
* 獲取緩存數(shù)據(jù)
* @returns ICacheData
*/
export const getCacheData = (): ICacheData => {
if (!isExists) return {
cacheTransformCount: 0,
cacheChunkCount: 0
};
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
};
/**
* 設(shè)置緩存數(shù)據(jù)
* @returns
*/
export const setCacheData = (data: ICacheData) => {
!isExists && fs.mkdirSync(dirPath);
fs.writeFileSync(filePath, JSON.stringify(data));
};
使用緩存
// 緩存進(jìn)度條計算
function runCachedData() {
if (transformCount === 1) {
stream.write('\n');
bar.tick({
transformTotal: cacheTransformCount,
transformCur: transformCount,
chunkTotal: cacheChunkCount,
chunkCur: 0,
})
}
transformed++
percent = lastPercent = +(transformed / (cacheTransformCount + cacheChunkCount)).toFixed(2)
}
實現(xiàn)架構(gòu)圖

最后
該系列會是一個持續(xù)更新系列,關(guān)于整個專欄 《Vite 從入門到精通》,我主要會從如下圖幾個方面講解,請大家拭目以待吧?。。?/p>

更多關(guān)于vite打包插件的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
vue-extend和vue-component注冊一個全局組件方式
這篇文章主要介紹了vue-extend和vue-component注冊一個全局組件方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-11-11
vue實現(xiàn)手機(jī)號碼的校驗實例代碼(防抖函數(shù)的應(yīng)用場景)
這篇文章主要給大家介紹了關(guān)于vue實現(xiàn)手機(jī)號碼的校驗的相關(guān)資料,主要是防抖函數(shù)的應(yīng)用場景,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用vue具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09
vue3插槽:el-table表頭插入tooltip及更換表格背景色方式
這篇文章主要介紹了vue3插槽:el-table表頭插入tooltip及更換表格背景色方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-06-06

