最近在使用?Vite4.0
?構(gòu)建一個(gè)中型前端項(xiàng)目的過程中,遇到了一些坑,也做了一些項(xiàng)目在構(gòu)建生產(chǎn)環(huán)境時(shí)的優(yōu)化,在這里做一個(gè)記錄,以便后期查閱。(完整配置在后面)
上面是dist文件夾的截圖,里面的內(nèi)容已經(jīng)有30mb了,是時(shí)候該做點(diǎn)什么了。
分析
想要實(shí)現(xiàn)優(yōu)化,首先我得先知道,是什么占了這么大的空間。是圖片?是庫?還是其他靜態(tài)資源?
-
將文件分門別類,js,css這些資源目錄分別打包到對應(yīng)的文件夾下
js 復(fù)制代碼build:?{ ????rollupOptions:?{ ??????output:?{ ????????chunkFileNames:?'js/[name]-[hash].js',?//?引入文件名的名稱 ????????entryFileNames:?'js/[name]-[hash].js',?//?包的入口文件名稱 ????????assetFileNames:?'[ext]/[name]-[hash].[ext]',?//?資源文件像?字體,圖片等 ??????} ????} }
-
查看項(xiàng)目的依賴,找出大塊頭
rollup-plugin-visualizer是一個(gè)打包體積分析插件,對應(yīng)webpack中的
webpack-bundle-analyzer
。配置好后運(yùn)行構(gòu)建命令會(huì)生成一個(gè)stats.html
。
bash
復(fù)制代碼npm?i?rollup-plugin-visualizer?-D
js
復(fù)制代碼import?{?visualizer?}?from?'rollup-plugin-visualizer'
js
復(fù)制代碼plugins:?[
????visualizer({open:?true})
]
arduino
復(fù)制代碼npm?run?build?//?打包結(jié)束后會(huì)出現(xiàn)下圖
?
從體積能看到,這里已經(jīng)達(dá)到了7MB大小了,是時(shí)候該做點(diǎn)什么了。
優(yōu)化
拆分包
這里有一個(gè)自己的個(gè)人見解:如果不同模塊使用的插件基本相同那就盡可能打包在同一個(gè)文件中,減少http請求,如果不同模塊使用不同插件明顯,那就分成不同模塊打包。這是一個(gè)矛盾體。這里使用的是最小化拆分包。如果是前者可以直接選擇返回'vendor'。
scss
復(fù)制代碼rollupOptions: {
output: {
manualChunks(id) {
if (id.includes("node_modules")) {
// 讓每個(gè)插件都打包成獨(dú)立的文件
return id .toString() .split("node_modules/")[1] .split("/")[0] .toString();
}
}
}
}
去除debugger
bash
復(fù)制代碼npm?i?terser?-D
js
復(fù)制代碼terserOptions:?{
??compress:?{
????drop_console:?true,
????drop_debugger:?true
??}
}
CDN 加速
內(nèi)容分發(fā)網(wǎng)絡(luò)(Content Delivery Network,簡稱 CDN)就是讓用戶從最近的服務(wù)器請求資源,提升網(wǎng)絡(luò)請求的響應(yīng)速度。同時(shí)減少應(yīng)用打包出來的包體積,利用瀏覽器緩存,不會(huì)變動(dòng)的文件長期緩存。(不建議使用第三方cdn,這里做學(xué)習(xí)討論使用)
bash
復(fù)制代碼npm?i?rollup-plugin-external-globals?-D
npm?i?vite-plugin-html?-D
html
復(fù)制代碼<head>
????<%-?vuescript?%>
</head>
css
復(fù)制代碼import?{?createHtmlPlugin?}?from?'vite-plugin-html'
rollupOptions:?{
??//?告訴打包工具?在external配置的?都是外部依賴項(xiàng)??不需要打包
??external:?['vue'],
??plugins:?[
????externalGlobals({
??????//?"在項(xiàng)目中引入的變量名稱":"CDN包導(dǎo)出的名稱,一般在CDN包中都是可見的"
??????vue:?'Vue'
????})
??]
}
plugins:?[
????createHtmlPlugin({
??????minify:?true,
??????inject:?{
????????data:?{
??????????vuescript:?'<script?src="https://cdn.jsdelivr.net/npm/vue@3.2.37"></script>'
????????}
??????}
????})
]
?
按需導(dǎo)入
仔細(xì)看上面那張圖右下部分的模塊,不知道你會(huì)不會(huì)感覺到奇怪,明明是同一個(gè)包,為什么既出現(xiàn)了lodash又出現(xiàn)了lodash-es。其實(shí)lodash-es 是 lodash 的 es modules 版本 ,是著具備 ES6 模塊化的版本,體積小,而lodash是common.js版本。lodash最大的缺陷就是無法按需導(dǎo)入。
js
復(fù)制代碼import?_?from?'lodash-es';?//?你將會(huì)把整個(gè)lodash的庫引入到項(xiàng)目
import?{?cloneDeep?}?from?'lodash-es';?//?你將會(huì)把引入cloneDeep引入到項(xiàng)目
項(xiàng)目中用到lodash的地方也不多,經(jīng)過手動(dòng)修改一下,看現(xiàn)在已經(jīng)看不到lodash的庫了。
文件壓縮
復(fù)制代碼npm?install?vite-plugin-compression?-D
js
復(fù)制代碼//?build.rollupOptions.plugins[]
viteCompression({
??verbose:?true,?//?是否在控制臺(tái)中輸出壓縮結(jié)果
??disable:?false,
??threshold:?10240,?//?如果體積大于閾值,將被壓縮,單位為b,體積過小時(shí)請不要壓縮,以免適得其反
??algorithm:?'gzip',?//?壓縮算法,可選['gzip','?brotliccompress?','deflate?','deflateRaw']
??ext:?'.gz',
??deleteOriginFile:?true?//?源文件壓縮后是否刪除(我為了看壓縮后的效果,先選擇了true)
})
當(dāng)請求靜態(tài)資源時(shí),服務(wù)端發(fā)現(xiàn)請求資源為gzip的格式時(shí),應(yīng)該設(shè)置響應(yīng)頭?content-encoding: gzip
?。因?yàn)闉g覽器解壓也需要時(shí)間,所以代碼體積不是很大的話不建議使用?gzip
?壓縮。
圖片壓縮
bash
復(fù)制代碼yarn?add?vite-plugin-imagemin?-D
or
bash
復(fù)制代碼npm?i?vite-plugin-imagemin?-D
js
復(fù)制代碼import?viteImagemin?from?'vite-plugin-imagemin'
plugin:?[
????viteImagemin({
??????gifsicle:?{
????????optimizationLevel:?7,
????????interlaced:?false
??????},
??????optipng:?{
????????optimizationLevel:?7
??????},
??????mozjpeg:?{
????????quality:?20
??????},
??????pngquant:?{
????????quality:?[0.8,?0.9],
????????speed:?4
??????},
??????svgo:?{
????????plugins:?[
??????????{
????????????name:?'removeViewBox'
??????????},
??????????{
????????????name:?'removeEmptyAttrs',
????????????active:?false
??????????}
????????]
??????}
????})
]
viteImagemin
在國內(nèi)比較難安裝,容易出現(xiàn)報(bào)錯(cuò),可以嘗試一下下面幾種解決方案。
viteImagemin報(bào)錯(cuò)
-
使用 yarn 在 package.json 內(nèi)配置(推薦) "resolutions": { "bin-wrapper": "npm:bin-wrapper-china" }
-
使用 npm,在電腦 host 文件加上如下配置即可 199.232.4.133 raw.githubusercontent.com
-
使用 cnpm 安裝(不推薦)
填坑
坑1
在優(yōu)化過程中發(fā)現(xiàn)有什么rollupOption不生效,請檢查vite版本。上述配置在vite4.0版本生效,如需升級,請前往官方遷移文檔。
坑2
Uncaught TypeError: Failed to resolve module specifier "Vue". Relative references must start with either "/", "./", or "../".
這里有可能是?vue-demi
?引入了?vue
,然而?rollup-plugin-external-globals
?插件配置全局變量時(shí)不會(huì)處理?node_modules
?下的依賴項(xiàng),導(dǎo)致?vue-demi
?還是通過?import
?的方式與?node_modules
?下的?vue
?進(jìn)行關(guān)聯(lián),而沒有使用全局變量下的?vue
,打包后?vue
?已變成外部依賴項(xiàng),vue-demi
?自然無法找到?vue
,所以就報(bào)錯(cuò)了。
而vue-demi
是哪里來的呢,我的項(xiàng)目是由于element-plus
引用了vue-demi
,所以此時(shí)解決方案就是將vue-demi
也用cdn引入。
總結(jié)
到了這一步,整個(gè)文件夾已經(jīng)完全瘦身了。從一開始的30MB到現(xiàn)在的11.8MB了。我們在項(xiàng)目里面放置了許多json數(shù)據(jù)(因?yàn)闃I(yè)務(wù)原因不能上傳到服務(wù)器),json數(shù)據(jù)已經(jīng)占了差不多5、6mb的原因,所以是一個(gè)單純的項(xiàng)目并沒有這么大。
?文章來源:http://www.zghlxwxcb.cn/news/detail-694513.html
?文章來源地址http://www.zghlxwxcb.cn/news/detail-694513.html
配置
js
復(fù)制代碼//?vite.config.js
import?{?defineConfig?}?from?'vite'
import?{?createHtmlPlugin?}?from?'vite-plugin-html'
import?viteImagemin?from?'vite-plugin-imagemin'
import?externalGlobals?from?'rollup-plugin-external-globals'
import?{?visualizer?}?from?'rollup-plugin-visualizer'
import?viteCompression?from?'vite-plugin-compression'
//?https://vitejs.dev/config/
export?default?defineConfig({
??plugins:?[
????visualizer({?open:?true?}),
????//?將下面的添加到plugin下
????createHtmlPlugin({
??????minify:?true,
??????inject:?{
????????data:?{
??????????vuescript:?'<script?src="https://cdn.jsdelivr.net/npm/vue@3.2.25"></script>',
??????????demiScript:?'<script?src="http://cdn.jsdelivr.net/npm/vue-demi@0.13.7"></script>',
??????????elementPlusScript:?`
????????????<link?>
????????????<script?src="https://cdn.jsdelivr.net/npm/element-plus@2.2.22/dist/index.full.min.js"></script>
??????????`,
??????????echartsSciprt:?'<script?src="https://cdn.jsdelivr.net/npm/echarts@5.0.2/dist/echarts.min.js"></script>'
????????}
??????}
????}),
????viteImagemin({
??????gifsicle:?{
????????optimizationLevel:?7,
????????interlaced:?false
??????},
??????optipng:?{
????????optimizationLevel:?7
??????},
??????mozjpeg:?{
????????quality:?20
??????},
??????pngquant:?{
????????quality:?[0.8,?0.9],
????????speed:?4
??????},
??????svgo:?{
????????plugins:?[
??????????{
????????????name:?'removeViewBox'
??????????},
??????????{
????????????name:?'removeEmptyAttrs',
????????????active:?false
??????????}
????????]
??????}
????})
??],
??build:?{
????target:?'es2020',
????minify:?'terser',
????//?rollup?配置
????rollupOptions:?{
??????output:?{
????????chunkFileNames:?'js/[name]-[hash].js',?//?引入文件名的名稱
????????entryFileNames:?'js/[name]-[hash].js',?//?包的入口文件名稱
????????assetFileNames:?'[ext]/[name]-[hash].[ext]',?//?資源文件像?字體,圖片等
????????manualChunks(id)?{
??????????if?(id.includes('node_modules'))?{
????????????return?'vendor'
??????????}
????????}
??????},
??????//??告訴打包工具?在external配置的?都是外部依賴項(xiàng)??不需要打包
??????external:?['vue',?'element-plus',?'echarts'],
??????plugins:?[
????????externalGlobals({
??????????vue:?'Vue',
??????????'element-plus':?'ElementPlus',
??????????echarts:?'echarts',
??????????'vue-demi':?'VueDemi'
????????}),
????????viteCompression({
??????????verbose:?true,?//?是否在控制臺(tái)中輸出壓縮結(jié)果
??????????disable:?false,
??????????threshold:?10240,?//?如果體積大于閾值,將被壓縮,單位為b,體積過小時(shí)請不要壓縮,以免適得其反
??????????algorithm:?'gzip',?//?壓縮算法,可選['gzip','?brotliccompress?','deflate?','deflateRaw']
??????????ext:?'.gz',
??????????deleteOriginFile:?false?//?源文件壓縮后是否刪除
????????})
??????]
????},
????terserOptions:?{
??????compress:?{
????????//?生產(chǎn)環(huán)境時(shí)移除console
????????drop_console:?true,
????????drop_debugger:?true
??????}
????}
??}
})
到了這里,關(guān)于Vite打包性能優(yōu)化及填坑的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!