一、首先來個 Vite 的通用簡介
Vite 是一種新型前端構建工具,在我們保險前端專案中已經推動並應用很久了,Vite 能夠顯著降低構建時間,提升前端開發效率。
它主要由兩部分組成:
- 一個開發伺服器,它基於 原生 ES 模組 提供了 豐富的內建功能,如速度快到驚人的 模組熱更新(HMR)
- 一套構建指令,它使用 Rollup 打包你的程式碼,並且它是預配置的,可輸出用於生產環境的高度最佳化過的靜態資源
Vite 還提供了強大的擴充套件性,可透過其 外掛 API 和 JavaScript API 進行擴充套件,並提供完整的型別支援。
二、Vite 的優勢,為什麼使用 Vite ?
當我們開始構建越來越大型的應用時,需要處理的 JavaScript 程式碼量也呈指數級增長。包含數千個模組的大型專案相當普遍。基於 JavaScript 開發的工具就會開始遇到效能瓶頸:通常需要很長時間(甚至是幾分鐘!)才能啟動開發伺服器,即使使用模組熱替換(HMR),檔案修改後的效果也需要幾秒鐘才能在瀏覽器中反映出來。如此迴圈往復,嚴重影響開發人員的效率。
當冷啟動開發伺服器時,基於打包器的方式啟動必須優先抓取並構建你的整個應用,然後才能提供服務,如果專案很大,導致的一個必然結果就是,服務啟動很慢,熱更新很慢,效率降低。Vite 只需要在瀏覽器請求原始碼時進行轉換並按需提供原始碼。根據情景動態匯入程式碼,即只在當前螢幕上實際使用時才會被處理,節省啟動及更新時間。
如下圖是新舊專案啟動時長對比,Vite 啟動速度,快了 30 多倍;
常規的透過 webpack 啟動的服務,基於打包器啟動,整個重新構建,即使將構建內容放到快取中,更新速度也會隨著應用體積增長而直線下降:
Vite 在原生 ESM 基礎上執行 HMR,Vite 只需要精確地使已編輯的模組與其最近的 HMR 邊界之間的鏈失活(大多數時候只是模組本身),使得無論應用大小如何,HMR 始終能保持快速更新:
三、Vite 為我們開發提升了很大的效率,但是也會有一些小問題
1、使用 Vite + Vue3 +Element-plus 或者其他 UI 庫,按需載入使用時,多人開發,每人頁面重新 reload 了嗎🤓?
2、低版本 Vite(2.9以下)配置 Preview 的 proxy 時,是不是不生效🤓?
3、低版本 Vite 配合 unocss 設定樣式後,是不是熱更新不生效🤓?
4、部分依賴包,使用京東映象,是不是無法下載🤓?
如果你遇到了以上問題,那這邊文章可以幫助你解決困惑!
四、解決頁面 reload 問題:高低版本 Vite 解決方法不同
- 原因:UI 庫配置按需載入,點選跳轉新頁面,導致重新 reload 頁面
- 情況:高低版本 Vite 解決頁面 reload 方法不同
問題現象如下,上方圖片頁面會 reload,會有一段時間白屏,下方圖片中檔案 preload:
1、Vite 低版本(v2.9以下)頁面 reload 解決方法;
- 解決方法:提前進行依賴包的預載入,可透過如下兩種方法配置,推薦方法b(因為低版本有現成外掛);
- 透過這些配置,就能夠使頁面 reload 在多人開發時只進行一次。
注意事項(低版本 Vite 的 bug,高版本已經修復):
- 使用 unocss 時,熱更新會失效,需要手動重新整理頁面,如果不使用 unocss 影響不大
方法a、透過手動配置 vite.config.ts 檔案的 optimizeDeps 選項;
// vite.config.js
{
...
optimizeDeps: {
include: [
'vue',
'vue-router',
'pinia',
'@element-plus/icons-vue',
'driver.js',
'element-plus',
'element-plus/es',
'element-plus/es/components/alert/style/index',
'element-plus/es/components/badge/style/index',
'element-plus/es/components/breadcrumb-item/style/index',
'element-plus/es/components/breadcrumb/style/index',
'element-plus/es/components/button/style/index',
'element-plus/es/components/card/style/index'
...
]
}
}
方法b、使用現成的外掛 vite-plugin-optimize-persist、vite-plugin-package-config (推薦原因: 自動會生成預載入配置檔案 optimizeDeps),通用配置如下:
😂遺憾的是高版本(v2.9及以上失效)配置無效,有興趣的話,可以試著修改下原始碼。
// vite.config.ts
// 兩個外掛組合使用,會自動生成 optimizeDeps 配置,預設生成到 package.json 檔案中,可透過 PkgConfig() 修改生成目錄
import OptimizationPersist from 'vite-plugin-optimize-persist'
import PkgConfig from 'vite-plugin-package-config'
export default {
...
plugins: [
...
PkgConfig(),
OptimizationPersist()
]
}
2、Vite 高版本(v4+)頁面 reload 解決方法:
- 解決方法:上述兩個外掛已被棄用,只能自己配置 optimizeDeps 選項,提前進行依賴包的預載入;
全量配置案例如下,備註:如果專案中使用,根據專案需要進行相應依賴包的配置,否則會出現首屏載入過慢的問題,類似我們常規使用的 webpack 一樣;
// vite.config.js
{
...
optimizeDeps:{
include: [
'@element-plus/icons-vue',
'@tinymce/tinymce-vue',
'@vueuse/core',
'@vueuse/shared',
'axios',
'clipboard',
'codemirror',
'codemirror/addon/lint/json-lint',
'codemirror/addon/lint/lint',
'codemirror/mode/css/css',
'codemirror/mode/htmlmixed/htmlmixed',
'codemirror/mode/javascript/javascript',
'driver.js',
'element-plus',
'element-plus/es',
'element-plus/es/components/alert/style/index',
'element-plus/es/components/badge/style/index',
'element-plus/es/components/breadcrumb-item/style/index',
'element-plus/es/components/breadcrumb/style/index',
'element-plus/es/components/button/style/index',
'element-plus/es/components/card/style/index',
'element-plus/es/components/cascader/style/index',
'element-plus/es/components/check-tag/style/index',
'element-plus/es/components/checkbox-group/style/index',
'element-plus/es/components/checkbox/style/index',
'element-plus/es/components/col/style/index',
'element-plus/es/components/color-picker/style/index',
'element-plus/es/components/config-provider/style/index',
'element-plus/es/components/date-picker/style/index',
'element-plus/es/components/dialog/style/index',
'element-plus/es/components/divider/style/index',
'element-plus/es/components/drawer/style/index',
'element-plus/es/components/dropdown-item/style/index',
'element-plus/es/components/dropdown-menu/style/index',
'element-plus/es/components/dropdown/style/index',
'element-plus/es/components/empty/style/index',
'element-plus/es/components/form-item/style/index',
'element-plus/es/components/form/style/index',
'element-plus/es/components/icon/style/index',
'element-plus/es/components/input-number/style/index',
'element-plus/es/components/input/style/index',
'element-plus/es/components/link/style/index',
'element-plus/es/components/loading/style/index',
'element-plus/es/components/menu-item/style/index',
'element-plus/es/components/menu/style/index',
'element-plus/es/components/message-box/style/index',
'element-plus/es/components/message/style/index',
'element-plus/es/components/notification/style/index',
'element-plus/es/components/option/style/index',
'element-plus/es/components/pagination/style/index',
'element-plus/es/components/popover/style/index',
'element-plus/es/components/progress/style/index',
'element-plus/es/components/radio-group/style/index',
'element-plus/es/components/radio/style/index',
'element-plus/es/components/row/style/index',
'element-plus/es/components/scrollbar/style/index',
'element-plus/es/components/select/style/index',
'element-plus/es/components/space/style/index',
'element-plus/es/components/step/style/index',
'element-plus/es/components/steps/style/index',
'element-plus/es/components/sub-menu/style/index',
'element-plus/es/components/switch/style/index',
'element-plus/es/components/tab-pane/style/index',
'element-plus/es/components/table-column/style/index',
'element-plus/es/components/table/style/index',
'element-plus/es/components/tabs/style/index',
'element-plus/es/components/tag/style/index',
'element-plus/es/components/timeline-item/style/index',
'element-plus/es/components/timeline/style/index',
'element-plus/es/components/tooltip/style/index',
'element-plus/es/components/transfer/style/index',
'element-plus/es/components/upload/style/index',
'element-plus/es/components/popconfirm/style/index',
'element-plus/es/components/backtop/style/index',
'element-plus/es/components/affix/style/index',
'element-plus/es/components/statistic/style/index',
'element-plus/es/components/tree/style/index',
'element-plus/es/components/tree-v2/style/index',
'element-plus/es/components/tree-select/style/index',
'element-plus/es/components/table-v2/style/index',
'element-plus/es/components/skeleton/style/index',
'element-plus/es/components/skeleton-item/style/index',
'element-plus/es/components/collapse/style/index',
'element-plus/es/components/collapse-item/style/index',
'element-plus/es/components/collapse-transition/style/index',
'element-plus/es/components/carousel/style/index',
'element-plus/es/components/carousel-item/style/index',
'element-plus/es/components/calendar/style/index',
'element-plus/es/components/badge/style/index',
'element-plus/es/components/avatar/style/index',
'element-plus/es/components/aside/style/index',
'element-plus/es/locale/lang/zh-cn',
'fuse.js',
'js-base64',
'js-cookie',
'js-file-download',
'nprogress',
'pako',
'path-browserify',
'path-to-regexp',
'pinia',
'prismjs',
'qs',
'screenfull',
'sortablejs',
'vue',
'vue-json-pretty',
'vue-router',
'vuedraggable'
]
}
}
五、解決 Vite 低版本(v2.9以下),preview 配置 proxy 不生效:
問題原因:低版本 Vite 的執行 preview 預覽時,使用的 proxy 是 server 中的 proxy 配置,官方文件中提供的 preview 的 proxy 無效,這是低版本 Vite 的一個 bug,高版本已經修復,github 上有相關的 issue,也可以透過原始碼檢視。
解決辦法:
-
在 vite.config.js 使用 server 中的 proxy 代替
-
使用 switchhost 進行代理配置
六、解決 Vite 低版本(v2.9以下),unocss 熱更新失效:
-
解決方法a:升級 Vite,從根本解決問題,以後專案升級比較方便,各種小問題容易規避,推薦升級
-
解決方法b:降低 unocss 的版本,可能會出現各種其他問題,不建議
針對這個問題,作者沒有降低 unocss 的版本,直接進行 Vite 升級,如果使用 unocss 強烈建議進行 Vite 升級;
不升級後期如果使用其他的依賴包,可能也會有各種其他問題出現
七、解決升級 Vite 專案後,部分依賴包,使用京東映象無法下載:
產生原因:各種依賴包之間互相依賴,京東映象的 npm 包可能有問題;
解決方法:非京東私有依賴包,使用 npm 官方映象下載,京東私有映象使用京東映象,初始化專案,生成 package-lock.json 檔案,多人合作時,以 package-lock.json 檔案為主。
總結:Vite 幫助我們提升開發效率,但是區分 Vite 是否需要使用最新版本,還是需要作為考慮依據:
如果你的專案不使用 unocss,同時對於 preview 下的 proxy 沒有特殊要求,那麼 Vite2.8.6 + Vue3 + elementPlus 可自動生成預載入檔案,省時省力,開發體驗好,強烈推薦;如果你的專案使用 unocss 或者對於 preview 下的 proxy 有特殊需求,強烈建議使用最新版本的 Vite,可透過手動配置 optimizeDeps 解決頁面重新整理的問題。
作者:京東保險 王升升
來源:京東雲開發者社群 轉載請註明來源