Vite和Webpack的核心差異
寫在開頭
最近的 vite比較火,而且發(fā)布了2.0版本,vue的作者也是在極力推薦在之前的文章里面我提到過, vite的缺點在于目前的生態(tài)不夠webpack成熟,但是只要能彌補這個缺點,便有很大概率能替代目前webpack的大部分市場
全方位對比vite和webpack
webpack打包過程
1.識別入口文件
2.通過逐層識別模塊依賴。(Commonjs、amd或者es6的import,webpack都會對其進行分析。來獲取代碼的依賴)
3.webpack做的就是分析代碼。轉換代碼,編譯代碼,輸出代碼
4.最終形成打包后的代碼
webpack打包原理
1.
先逐級遞歸識別依賴,構建依賴圖譜2.將代碼轉化成AST抽象語法樹
3.在AST階段中去處理代碼
4.把AST抽象語法樹變成瀏覽器可以識別的代碼, 然后輸出
重點:這里需要遞歸識別依賴,構建依賴圖譜。圖譜對象就是類似下面這種
{ './app.js':
{ dependencies: { './test1.js': './test1.js' },
code:
'"use strict";\n\nvar _test = _interopRequireDefault(require("./test1.js"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }\n\nconsole.log(test
1);' },
'./test1.js':
{ dependencies: { './test2.js': './test2.js' },
code:
'"use strict";\n\nvar _test = _interopRequireDefault(require("./test2.js"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }\n\nconsole.log(\'th
is is test1.js \', _test["default"]);' },
'./test2.js':
{ dependencies: {},
code:
'"use strict";\n\nObject.defineProperty(exports, "__esModule", {\n value: true\n});\nexports["default"] = void 0;\n\nfunction test2() {\n console.log(\'this is test2 \');\n}\n\nvar _default = tes
t2;\nexports["default"] = _default;' } }

vite原理
當聲明一個 script 標簽類型為 module 時
如:
<script type="module" src="/src/main.js"></script>
瀏覽器就會像服務器發(fā)起一個GET
http://localhost:3000/src/main.js請求main.js文件:
// /src/main.js:
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')
瀏覽器請求到了main.js文件,檢測到內部含有import引入的包,又會對其內部的 import 引用發(fā)起 HTTP 請求獲取模塊的內容文件
如:
GET http://localhost:3000/@modules/vue.js如:
GET http://localhost:3000/src/App.vueVite的主要功能就是通過劫持瀏覽器的這些請求,并在后端進行相應的處理將項目中使用的文件通過簡單的分解與整合,然后再返回給瀏覽器,vite整個過程中沒有對文件進行打包編譯,所以其運行速度比原始的webpack開發(fā)編譯速度快出許多!
webpack缺點一。緩慢的服務器啟動
當冷啟動開發(fā)服務器時,基于打包器的方式是在提供服務前去急切地抓取和構建你的整個應用。
vite改進
Vite 通過在一開始將應用中的模塊區(qū)分為 依賴 和 源碼 兩類,改進了開發(fā)服務器啟動時間。
依賴 大多為純 JavaScript 并在開發(fā)時不會變動。一些較大的依賴(例如有上百個模塊的組件庫)處理的代價也很高。依賴也通常會以某些方式(例如 ESM 或者 CommonJS)被拆分到大量小模塊中。
Vite 將會使用 esbuild 預構建依賴。Esbuild 使用 Go 編寫,并且比以 JavaScript 編寫的打包器預構建依賴快 10-100 倍。
源碼 通常包含一些并非直接是 JavaScript 的文件,需要轉換(例如 JSX,CSS 或者 Vue/Svelte 組件),時常會被編輯。同時,并不是所有的源碼都需要同時被加載。(例如基于路由拆分的代碼模塊)。
Vite 以 原生 ESM 方式服務源碼。這實際上是讓瀏覽器接管了打包程序的部分工作:Vite 只需要在瀏覽器請求源碼時進行轉換并按需提供源碼。根據(jù)情景動態(tài)導入的代碼,即只在當前屏幕上實際使用時才會被處理。
webpack缺點2.使用的是node.js去實現(xiàn)

vite改進
Vite 將會使用 esbuild預構建依賴。Esbuild 使用 Go 編寫,并且比以Node.js編寫的打包器預構建依賴快 10-100 倍。
webpack致命缺點3.熱更新效率低下
當基于打包器啟動時,編輯文件后將重新構建文件本身。顯然我們不應該重新構建整個包,因為這樣更新速度會隨著應用體積增長而直線下降。
一些打包器的開發(fā)服務器將構建內容存入內存,這樣它們只需要在文件更改時使模塊圖的一部分失活[1],但它也仍需要整個重新構建并重載頁面。這樣代價很高,并且重新加載頁面會消除應用的當前狀態(tài),所以打包器支持了動態(tài)模塊熱重載(HMR):允許一個模塊 “熱替換” 它自己,而對頁面其余部分沒有影響。這大大改進了開發(fā)體驗 - 然而,在實踐中我們發(fā)現(xiàn),即使是 HMR 更新速度也會隨著應用規(guī)模的增長而顯著下降。
vite改進
在 Vite 中,HMR 是在原生 ESM 上執(zhí)行的。當編輯一個文件時,
Vite 只需要精確地使已編輯的模塊與其最近的 HMR 邊界之間的鏈失效(大多數(shù)時候只需要模塊本身),使 HMR 更新始終快速,無論應用的大小。Vite 同時利用 HTTP 頭來加速整個頁面的重新加載(再次讓瀏覽器為我們做更多事情):源碼模塊的請求會根據(jù) 304 Not Modified 進行協(xié)商緩存,而依賴模塊請求則會通過 Cache-Control: max-age=31536000,immutable 進行強緩存,因此一旦被緩存它們將不需要再次請求。
vite缺點1.生態(tài),生態(tài),生態(tài)不如webpack
wepback牛逼之處在于loader和plugin非常豐富,不過我認為生態(tài)只是時間問題,現(xiàn)在的vite,更像是當時剛出來的M1芯片Mac,我當時非常看好M1的Mac,毫不猶豫買了,現(xiàn)在也沒什么問題
vite缺點2.prod環(huán)境的構建,目前用的Rollup
原因在于esbuild對于css和代碼分割不是很友好
vite缺點3.還沒有被大規(guī)模使用,很多問題或者訴求沒有真正暴露出來
vite真正崛起那一天,是跟vue3有關系的,當vue3廣泛開始使用在生產(chǎn)環(huán)境的時候,vite也就大概率意味著被大家慢慢開始接受了
總結
Vite,就像剛出來的
M1芯片Mac,都說好,但是一開始買的人不多,擔心生態(tài)問題,后面都說真香相信vue3作者的大力支持下,
vite即將大放異彩!我已經(jīng)在我自己項目的生產(chǎn)環(huán)境中,開始使用vite!
