最終鼓起勇氣把公司五年的webpack老專案改成了vite
theme: awesome-green
一.【 升級原因 】
工程現狀:
1. 專案較早 + 程式碼量大 + 外掛類庫版本低 + 各個節點優化空間逐漸變小
2. 為接下來Pro工程瘦身做準備;
造成的困擾:
PS:在以上問題的基礎上,webpack已經變得非常不好用了
開發環境服務的不穩定性,嚴重影響開發效率和心情;
打包後輸出檔案過大,導致執行環境速度慢、系統性能低;
改造目標:
1. webpack 升級 為 vite;
2. node版本調整;
3. sass 版本升級;
二.【 改造思路 】
版本庫描述:
1. 整體保持[email protected]核心基礎庫不動
2. 使用[email protected]替換[email protected]
3. NodeJs版本v14.19.1升級到v18.7.0(後因版本過高,降回原版本v14.19.1)
4. Npm版本v6.14.16升級到v8.15.0
5. 升級[email protected]到[email protected](後因版本過高,降回原版本v4.7.2)
6. 使用[email protected]
7. 升級[email protected]到[email protected]
8. 引用[email protected]使vue2支援vite
思路描述:
按需調整和配置,修改編譯環境和執行環境的錯誤,最終經過測試階段,程式碼推送線上
分支保全方案:
origin/dev dev環境原始碼
origin/propre2 pre環境原始碼
origin/pro 線上環境原始碼
origin/config_vite_nyz_221108 vite配置測試分支
origin/config_webpack_backup_nyz_221109 webpack配置備份分支(拉取自pro分支)
三.【 升級報告 】
| 類目 | webpack(升級前) | vite(升級後) | | --------- | ------------ | ---------- | | 本地服務啟動時長 | 230 秒 | 3 秒 | | 修改後熱更新時長 | 23 秒 | 1 秒 | | 本地服務效能 | 更新慢 & 服務經常崩潰 | 更新快 & 服務穩定 | | 執行打包任務時長 | 300秒 | 55 秒 | | 打包後輸出檔案大小 | 37.0 MB | 19.8 MB | | 打包後輸出檔案個數 | 1372 個 | 787 個 | | 依賴包優化後個數 | 103 個 | 82 個 | | 執行環境相容性驗證 | -- | -- |
四.【 執行過程 】
- 初始化一個vite專案
// 注意:這裡vite的版本採用2.8.0的,最新的版本建立後續會出現問題
// 要選擇vanilla原生專案 , 因為選擇vue會預設走vue3,造成與當前版本不匹配
npm init [email protected]
- 將原專案的src資料夾和其他用到的檔案/資料夾移入新專案
- 合併package.json的依賴項,script命令拋棄webpack,保留vite的兩條指令
"scripts": {
"serve": "cross-env NODE_ENV=development vite",
"build": "cross-env NODE_ENV=production vite build"
},
- 刪除外層初始化的main.js,移入或保留原專案的main.js到src下
-
index.html修改入口引入方式
<script type="module" src="src/main.js"></script>
-
main.js修改根的掛載方式
``` // // 原始碼 // new Vue({ // el: '#app', // router, // store, // render: h => h(App) // })
// 目的碼 new Vue({ router, store, render: h => h(App) }).$mount('#app') ```
-
使用cnpm快速下載相關依賴包
cnpm install
-
NodeJs版本不一致,導致[node-sass]找不到並報錯,直接拉取latest版本
cnpm install --save-dev sass sass-loader node-sass
-
啟動本地服務報錯:require is not defined
原因:vite預設使用es6標準的 import 的匯入方式,不支援require引入
// 下載 cnpm install vite-plugin-require-transform
// vite.config.js 引入 import requireTransform from 'vite-plugin-require-transform' // vite.config.js 使用 defineConfig({ plugins: [ createVuePlugin(), requireTransform({ fileRegex: /.vue$|.js$|.json$|.ts$|.tsx$/ }) ] })
-
服務編譯的時候,頭部註釋資訊報錯 , 如下圖,
原因:語法編譯不通過
解決:涉及檔案較多,全部找出來注掉就可以了
-
編譯報錯:Failed to fetch dynamically imported module
原因:vue檔案引入錯誤,構建過程無法補全檔案字尾並讀取
解決:把vue和js相關引入程式碼全部加上字尾 ( 涉及程式碼較多,找出來全部改掉 )
-
樣式的deep語法報錯,找出來全部替換掉
/deep/ 替換為 ::v-deep
-
編譯報錯:process is not defined
// vite.config.js define: { 'process.env': {} }
-
專案中使用的環境變數報錯
解決:webpack升級vite後,需要建立環境變數檔案並使用vite的環境變數
process.env // webpack import.meta.env // vite
-
編譯報錯:Module “path” has been externalized for brower compatibility and cannot be accesed in client code
原因:path模組無法在客戶端程式碼中使用 , webpack自動幫我們處理了node內建模組 , vite沒有
解決:安裝 path-browserify 代替 path 模組
cnpm install path-browserify
import path from 'path' 改為 import path from 'path-browserify'
-
require相容配置,某些三方包中的require語法,在開發環境正常,打包環境報錯
// vite.config.js build:{ commonjsOptions: { transformMixedEsModules: true } }
-
打包報錯:[commonjs] Identifier '_vite_plugin_require_transform_Component' has already
原因:錯誤所指的意思是echarts 庫中宣告的變數已存在,還有再宣告的必要嗎?
解決:實則該變數並沒有重複宣告,所以改動CDN引入的方案,並刪掉頁面import引入語句
注意:CDN要引入對應的版本
jsdelivr相關庫檔案的CDN地址:http://www.jsdelivr.com/package/npm/echarts
// echart主入口和單獨引入的功能 改為cdn引入 // index.html 引入以下程式碼 <script src="http://cdn.jsdelivr.net/npm/[email protected]/dist/echarts.min.js"></script> <script src="http://cdn.jsdelivr.net/npm/[email protected]/map/js/china.js"></script>
-
打包報錯:'default' is not exported by node_modules/[email protected]@core-js
解決:rollup本身是不支援CommonJS的,使用了這個外掛,就可以解析CommonJS模組了
rollup.js相關配置資料:http://rollupjs.org/guide/en/#outputentryfilenames
cnpm install @rollup/plugin-commonjs -D
// vite.config.js import commonjs from '@rollup/plugin-commonjs'; plugins: [ commonjs() ]
-
打包報錯:Error: 'default' is not exported by node_modules/[email protected]
原因:該程式碼中的防抖節流方法沒有預設丟擲
解決:使用自定義封裝方法或工具庫平替即可
-
打包成功後部署至測試環境:Uncaught TypeError: Illegal invocation,報錯如下圖
原因:檢視報錯位置,可能是因為程式碼編譯轉換過程產生的錯誤
解決:故調整庫版本和引入方式
``` 1. es6-promise 引入方式調整
// require引入方式去掉 require('es6-promise').polyfill()
改為
// index.html 引入