當前位置:首頁 » 編程軟體 » vue大項目編譯慢

vue大項目編譯慢

發布時間: 2025-05-25 23:58:28

① 一次vue-cli4項目升級到vite的經歷

背景

使用vue-cli4的項目,業務寫多了之後開發運行和打包都慢了很多,為了提升開發體驗以及更新團隊技術框架,需要升級到更高級的腳手架上,兩種方案:一是升級到vue-cli5,二是升級到最新的vite。

其中第一種方案升級簡單,經過實驗,打包的速度不升反慢,這可能和項目中的有依賴以及業務代碼有關。

第二種方案升級vite,經過可行性調查,升級到vite的成功率非常高,最後決定從vue-cli4升級到vite,這是一個高風險高回報的事情,因為盡管市面上已存在很多升級成功的案列,但是每個項目都不一樣,我們的項目也很龐大,依賴很多,並沒有100%升級成功的把握。而升級成功的回報也很顯而易見,開發環境幾乎秒運行,開發體驗得到了顯著提升。

升級前後對比

||vue-cli4|vite||---|---|---||開發啟動時間|33306ms|1247ms||生產打包時間|78s|81s||打包體積|42.6MB|28.6MB||運行期間同一代碼改動編譯時間|1427ms|瞬時|

生產環境打包時間可能和我們項目中用到了太多vite插件有關系,但開發環境的提升非常顯著。

項目狀況

項目中用到的Vue2,VueCli版本:4.5.13,版本更新時間為2021.5.8,vueCli4的最後版本為4.5.17(2022.3.23),依賴的webpack版本為^4.0.0

組件庫使用vant,依賴Less預處理器,通過vue.config.js配置設置了less主題色,在webpack僅支持less-loader@5版本以及對應的less版本

業務css預處理器為stylus:"^0.54.5",對應stylus-loader:"^3.0.2"

進行了多頁打包(MPA)

使用了workbox-webpack-plugin插件配置了PWA:WorkboxWebpackPlugin

配置了多個路徑映射(alias別名)

指定了文件輸出路徑以及hash配置

生產環境下關閉proctionSourceMap以及css的sourceMap提升打包速度

proxy開啟多個代理

用到了.env文件中的環境變數

按照開發規范忽略部分文件後綴以及index.js

移除了preload腳本

期望結果

可以使用vite進行開發和打包

仍保留webpack打包功能(因為項目太大,不能保證升級到vite後會不會有問題,所以仍希望webpack原本功能正常運行)

准備工作

升級Node版本,vite只支持node12及以上,建議升級到v16以上。

安裝pnpm工具,pnpm作為更好的npm依賴管理工具,是目前npm和yarn的最好替代品,且有些依賴包使用npm安裝時會有異常,使用pnpm安裝可解決:pnpm

小項目嘗試一鍵轉換升級:wp2vite、webpack-to-vite,這兩個工具都提供了一鍵將webpack項目轉成vite的能力,但對於大中型項目,並不可靠。

開始行動1.安裝必要依賴pnpm?add?vite-plugin-env-compatible?vite-plugin-html?vite?vite-plugin-vue2?--dev

vite-plugin-vue2是處理vue2版本代碼的插件,如果項目中是vue3,安裝的依賴有所不同,請參考webpack-to-vite

2.復制html到根目錄,並修改

??注意是復制,並只改動復制後的html,這樣才不會破壞原有webpack功能。

修改復制後的html,增加對應的js文件引用,注意type屬性不能少!

<!--?忽略一些代碼?--><body>????<div?id="app"></div>????++?<script?type="mole"?src="/src/main.js"></script>?++</body>

多頁打包(MPA),其他頁面的html同樣操作,不同html引入對應的js即可。

3.新增vite.config.js文件,開始遷移最重要的配置部分

空配置如下:

import?{?defineConfig?}?from?'vite'export?default?defineConfig({})4.修改環境變數

環境變數主要面臨兩個問題:

要兼容webpack和vite的環境變數用法

解決方法:使用vite插件vite-plugin-env-compatible,讓vite中可以使用webpack中讀取環境變數的方式,再配合envPrefix配置,讓vite可以讀取到VUE_APP_開頭的環境變數:

?pnpm?add?vite-plugin-env-compatible?-D?import?{?defineConfig?}?from?'vite'?import?envCompatible?from?'vite-plugin-env-compatible'?export?default?defineConfig({???plugins:?[?????envCompatible()???],???envPrefix:?['VUE_APP_']?//?很重要?})?//?mian.js測試?console.log(process.env.VUE_APP_UNION_STATS)?console.log(import.meta.env.VUE_APP_UNION_STATS)

兩個列印都得到了正確的結果,注意:vite中默認只能讀取到VITE_開頭的環境變數,如果不配置envPrefix,則會導致第二個列印為undefind。

vite.config.js中不能讀取到環境變數

vite.config.js是無法直接通過import.meta.env和process.env獲取環境變數的,我們需要通過vite的loadEnv獲取。

我們需要將vite.config.js的導出對象改為函數:

?import?{?defineConfig,loadEnv?}?from?'vite'?export?default?({?mode?})?=>?{?????const?isPro?=?mode?===?'proction'?//?我們可以通過mode直接判斷當前是不是生產環境,注意mode可以在運行指令中指定:`vite?build?--mode?master`,如果沒有指定,那默認打包就是proction?????function?getEnv(key)?{?//?定義獲取環境變數的方法?????????return?loadEnv(mode,?process.cwd(),'')[key]?//?第三個參數非常重要,下面有詳解?????}?????return?defineConfig({?????????base:?getEnv('VUE_APP_PUBLICPATH'),?//?讀取環境變數?????????//?...忽略其他代碼?????})?})

loadEnv有三個參數,前兩個參數基本固定不變,而第三個參數默認情況下是不需要傳的,只有在配置了envPrefix項,讀取非VITE_開頭的變數時才需要,在loadEnv源碼中我們可以看到,第三個參數是prefixes:string|string[]='VITE_',也就是環境變數的前綴,默認是VITE_。

如果你的項目和我一樣,讀取了VUE_APP_PUBLICPATH這樣非VITE_開頭環境變數,就在loadEnv的第三個參數傳遞空字元串即可,這樣就能讀取到所有的環境變數了。

5.兼容commonjs代碼

項目中有用到commonjs規范的依賴,比如letmd5=require('js-md5').create(),webpack是基於node開發的,支持require語法,在打包的時候webpack也會正確處理這部分代碼,但在vite中不會,所以需要將這部分代碼改成importmd5from'js-md5'

項目開發環境下,一些node_moles中的包也會存在commonjs的代碼,我們可以通過vite的插件?vite-plugin-commonjs來實現這部分代碼的轉化,保證開發環境的正常運行。

pnpm?add?@originjs/vite-plugin-commonjs?--dev//?vite.config.js??忽略其他代碼import?{?viteCommonjs?}?from?'@originjs/vite-plugin-commonjs'export?default?({?mode?})?=>?{????return?defineConfig({????????plugins:?[????????????//?...????????????viteCommonjs()?//?兼容vite中的cjs導入語法????????]????})})6.解決css預處理的問題

vite內置了對主流css預處理器的支持(sass/less/stylus),項目使用預處理器時,只需要安裝對應預處理依賴即可:

#?.scss?and?.sasspnpm?add?sass?-D#?.lesspnpm?add?stylus?-D#?.styl?and?.styluspnpm?add?stylus?-D

比較巧的是,我們項目中用到的Stylus的@import別名的語法和vite沖突,@import'~@/public/stylus/mixins'這樣的代碼是會報錯,一開始我找到了插件,可以幫助我們解決這個問題:vite-plugin-stylus-alias,但是都後面打包的時候發現這個插件有副作用,後面採取了其他方法解決。

<!--?忽略一些代碼?--><body>????<div?id="app"></div>????++?<script?type="mole"?src="/src/main.js"></script>?++</body>0<!--?忽略一些代碼?--><body>????<div?id="app"></div>????++?<script?type="mole"?src="/src/main.js"></script>?++</body>1

使用這個插件會導致無法生成sourcemap文件,在打包的時候可以看到警告::aplugin(vite-plugin-stylus-alias)wasusedtotransformfiles,butdidn'.,鑒於插件作者已經很久沒有更新,建議能改成相對路徑還是直接改,如果引用地方較多,可以定義文件為全局styl文件最新解決方案:一般出現這個報錯是因為插件使用了vite的transformapi轉換代碼,但是return值缺失導致,解決方法:復制插件代碼到項目中,在插件transform函數return的結果中,返回map:null,然後再vite.config.js中引用項目中修改後的插件,即可完美解決,如下:文末解決bug有細說

<!--?忽略一些代碼?--><body>????<div?id="app"></div>????++?<script?type="mole"?src="/src/main.js"></script>?++</body>2

定義stylus全局文件

<!--?忽略一些代碼?--><body>????<div?id="app"></div>????++?<script?type="mole"?src="/src/main.js"></script>?++</body>3

這里需要注意,官方文檔中css-preprocessoroptions寫的是使用文件名拓展名作為key,stylus的文件拓展名是styl,但是我使用了stylus作為key並不會有問題,相反使用styl作為key則不生效了,後續這個地方可以留意一下。

在vite源碼中,stylus和styl都進行了判斷,理論上都可以使用,但目前測試的結果就是styl作為key不生效,可能源碼中其他地方還能找到原因。

7.組件庫按需導入和定製主題

我們項目中用到的組件庫是Vant2,該組件庫依賴Less,以及通過配置文件來定製組件的主題,在配置中我們需要進行修改:

vue-cli中的主題配置部分如下:

<!--?忽略一些代碼?--><body>????<div?id="app"></div>????++?<script?type="mole"?src="/src/main.js"></script>?++</body>4

vite中主題配置部分如下:

<!--?忽略一些代碼?--><body>????<div?id="app"></div>????++?<script?type="mole"?src="/src/main.js"></script>?++</body>5

按需導入項目中按需導入vant組件庫,組件可以成功導入,但是組件的樣式缺失了,這是因為在webpack中,babel-plugin-import插件幫我們實現了組件的樣式導入,在vite中使用?vite-plugin-style-import插件幫我們實現這個功能,不僅vant組件庫,其他諸如element、antv等組件庫也可以使用這個插件進行按需導入:

<!--?忽略一些代碼?--><body>????<div?id="app"></div>????++?<script?type="mole"?src="/src/main.js"></script>?++</body>6<!--?忽略一些代碼?--><body>????<div?id="app"></div>????++?<script?type="mole"?src="/src/main.js"></script>?++</body>78.修改alias別名配置,以及忽略文件後綴

vite配置別名的方法和vue-cli有所不同,且沒有默認的別名,都需要通過配置實現,且vite默認不能忽略文件後綴導入,我們也需要通過修改配置來實現:

<!--?忽略一些代碼?--><body>????<div?id="app"></div>????++?<script?type="mole"?src="/src/main.js"></script>?++</body>8

需要注意extensions配置的順序,從左到右進行匹配,如果存在同名但類型不同的文件,很可能得到期望外的結果,比如同目錄下存在index.js和index.vue,按上面的順序,import'./index?會優先匹配到index.js文件。這種情況建議補全後綴進行導入。

9.配置前端跨域

vite配置跨域和webpack也有出入,需要修改配置

<!--?忽略一些代碼?--><body>????<div?id="app"></div>????++?<script?type="mole"?src="/src/main.js"></script>?++</body>9

以上就是幾種常見的跨域配置方式,webpack中的devServer改為了server,webpack的proxy中的pathRewrite改成了rewrite,並且類型成為了函數,在函數中返回請求的路徑即可。

10.多頁打包以及打包的其他配置

vite在build.rollupOptions配置多頁打包,參考rollupOptions,其他配置參考文檔

import?{?defineConfig?}?from?'vite'export?default?defineConfig({})011.配置運行路徑

base是指項目運行在伺服器的哪個路徑下,一般通過從環境變數中動態獲取。

import?{?defineConfig?}?from?'vite'export?default?defineConfig({})112.配置EsLint

vite中使用vite-plugin-eslint插件實現eslint的檢查功能,安裝過程中發現[email protected]會報錯,安裝1.3.0版本即可。

import?{?defineConfig?}?from?'vite'export?default?defineConfig({})2import?{?defineConfig?}?from?'vite'export?default?defineConfig({})313.使用插件@vitejs/plugin-legacy兼容低版本瀏覽器

plugin-legacy文檔

import?{?defineConfig?}?from?'vite'export?default?defineConfig({})414.配置運行指令import?{?defineConfig?}?from?'vite'export?default?defineConfig({})5

可以在指令中聲明mode環境,這個mode在vite.config.js中可以得到,具體可以參考前面4.修改環境變數

保存運行指令npmrunserve開發環境已經可以跑起來了,但是vite的特性是你用到的頁面才會進行打包,其他頁面沒有進行訪問,是不會打包的,所以需要進行打包才能知道其他地方改造會不會有問題,打包如果有報錯,再解決報錯即可。

14.解決報錯

globalisnotdefined

這個錯誤是在node_moles/buffer/index.js?v=43e083a7文件中拋出的,我查看了yarn.lock文件,依賴路徑為多個vue-cli插件>[email protected]>node-libs-browser?>buffer

這個是依賴的問題,第一刪除node_moles重新安裝依賴。第二更換npm工具為pnpm重裝依賴,如果仍不行,建議不建議webpack,刪除掉webpack相關依賴。

網上還有一種做法是:在window對象上掛載global對象,可作為備選方案。

import?{?defineConfig?}?from?'vite'export?default?defineConfig({})6

@import'~@vant/icons/src/encode-woff2.less'報錯

這個錯誤是vant組件庫中的icon組件拋出的,vite默認不能使用別名,我們在前面配置了別名,但是配置的是~@指向項目中的src目錄,這樣vant組件庫的這個文件引用就找不到了。

issuesvant

解決方法:針對vant的這個文件,做一個別名,放到第一位,優先進行匹配:

import?{?defineConfig?}?from?'vite'export?default?defineConfig({})7

運行vitebuild,css產生了一些警告。

警告分為兩種,一是css中的屬性拼寫錯誤,諸如:color寫成了colo,background寫成了backgrounc,屬於語法錯誤,根據警告提示搜索對應樣式進行修改即可。

二是一些語法正確,但還不清楚為什麼壓縮時提示了警告:比如stylus修改scoped樣式用的>>>語法,以及background?rgba(0,0,0,0.5)提示Unexpected"rgba("。

/mole/exportsspecifiedinitspackage.json

這個錯誤是通過npminstall後運行vite指令報錯的,用yarn安裝一直很正常,原因是node_moles的某個包的package.json定義的main入口路徑錯了,所以找不到模塊導入。

解決方法:針對這個模塊,定義別名,指向正確的入口:

import?{?defineConfig?}?from?'vite'export?default?defineConfig({})8

打包後導入函數定義別名後,調用函數報錯

import*asminByfrom'lodash.minby'代碼報錯了,而且只有在生產環境下才產生。

解決方法:暫時去掉別名,這應該和lodash的導出方式moles.export在vite中轉化成ES語法的過程有關系。

importminByfrom'lodash.minby'

requireisnotdefine,通過require導入圖片資源報錯

前面在步驟5已經用了插件vite-plugin-commonjs轉化common.js的代碼了,require理應不會報錯。

但是require導入資源圖片算是webpack的功能,和js代碼不一樣,所以導入資源圖片的代碼都要進行修改:

require('./images/logo.png')改成importlogofrom'./images/logo.png'

這樣的修改可以兼容webpack和vite,這是在現有項目中,改動的地方會達到上百處,非常麻煩。

熱點內容
用逍遙安卓怎麼連接拍攝儀 發布:2025-05-26 04:50:07 瀏覽:265
我的世界人多的戰爭伺服器手機版 發布:2025-05-26 04:36:44 瀏覽:86
榮耀30支持哪些配置 發布:2025-05-26 04:03:56 瀏覽:303
手機視頻怎麼上傳到電腦 發布:2025-05-26 04:03:21 瀏覽:910
安卓手機微信小字體怎麼打 發布:2025-05-26 04:02:39 瀏覽:892
android文本邊框 發布:2025-05-26 03:57:39 瀏覽:282
朗逸6萬多是什麼配置 發布:2025-05-26 03:40:32 瀏覽:872
24節氣演算法 發布:2025-05-26 03:19:43 瀏覽:890
安卓QQ記錄怎麼傳到蘋果手機 發布:2025-05-26 03:15:26 瀏覽:946
雲伺服器怎麼維護 發布:2025-05-26 02:48:00 瀏覽:306