從零實(shí)現(xiàn) vite(先導(dǎo)篇)
mono-vite
基本知識(shí)
假設(shè)我們有如下兩個(gè) JS 文件。

即兩個(gè) esm 的模塊, 并且 main.mjs 依賴 utils.mjs。
如上代碼可以被支持 ESM 的瀏覽器所識(shí)別,但并不意味著其可以直接被運(yùn)行。比如我的代碼依賴了 npm 包和一些相對(duì)路徑,這些瀏覽器是無(wú)法識(shí)別的。
而 vite 則解決了這個(gè)問(wèn)題。由于 vite 本質(zhì)還是依賴了瀏覽器的特性,因此可以直接利用瀏覽器的諸如緩存的特點(diǎn)來(lái)提高性能。
除此之外, 每次修改文件,比如修改上面的 main.mjs 或者 utils.mjs 中的任意一個(gè)文件并不會(huì)導(dǎo)致“打包”全部文件。這是因?yàn)?vite 根本沒有打包過(guò)程, 而是直接將修改過(guò)的文件熱更新到瀏覽器的內(nèi)存中。
比如,我修改了 main.js,那么就直接發(fā)送一個(gè) http 去請(qǐng)求最新的 main.mjs 文件,而 utils.mjs 則可以繼續(xù)使用瀏覽器緩存中的內(nèi)容即可。
我畫了一個(gè)簡(jiǎn)單的原理圖給大家參考一下。

模塊之間的關(guān)系如上圖所示。并且這個(gè)時(shí)序指的是「更新一個(gè)文件之后的更新流程」。
我將其分成了若干模塊,它們分別是:
瀏覽器。用于處理 ESM 文件系統(tǒng)。用于存儲(chǔ)源代碼文件。 vite-server。響應(yīng)瀏覽器,并返回內(nèi)容。這些內(nèi)容主要是最新的文件系統(tǒng)中的文件,除此外還有注入到 client 中的代碼等。 hrm-sever。用于根據(jù)模塊的依賴關(guān)系確定應(yīng)該更新的模塊,并觸發(fā)相應(yīng)的回調(diào)函數(shù)。 watcher。監(jiān)聽文件系統(tǒng)的變更,當(dāng)文件內(nèi)容發(fā)生變化的時(shí)候,通知 hmr-server。之后 hmr-server 再去通過(guò) websocket 通知瀏覽器獲取最新的模塊(按需請(qǐng)求)。
如何確定需要更新的模塊
我們可以根據(jù) esm 的 import 關(guān)系生成一個(gè)依賴圖。并將圖中的所有點(diǎn)都放入一個(gè)哈希表中,key 可以是文件的請(qǐng)求路徑,value 可以是模塊本身,這樣就可以根據(jù)請(qǐng)求路徑在 的時(shí)間獲取到指定的節(jié)點(diǎn)。之后我們可以遍歷依賴圖,并依次發(fā)起瀏覽器的 http 請(qǐng)求獲取最新內(nèi)容,并觸發(fā)回調(diào)函數(shù)。
如下圖紅色的模塊被更新,我們通過(guò) 時(shí)間獲取到它,然后依次遍歷虛線的兩個(gè)模塊,發(fā)起請(qǐng)求獲取其最新模塊內(nèi)容,最后觸發(fā)注冊(cè)到這「三個(gè)」模塊上的回調(diào)函數(shù)即可。
?回調(diào)函數(shù)通過(guò) module.hot.accept 注冊(cè),具體參考 hmr 相關(guān)文檔。
?

一個(gè)更復(fù)雜的例子:

之后我會(huì)根據(jù)這個(gè)原理圖帶大家一步步實(shí)現(xiàn)一個(gè) mono-vite(等西法有時(shí)間的)。
愛心三連擊
1.看到這里了就點(diǎn)個(gè)在看支持下吧,你的在看是我創(chuàng)作的動(dòng)力。
2.關(guān)注公眾號(hào)腦洞前端,獲取更多前端硬核文章!加個(gè)星標(biāo),不錯(cuò)過(guò)每一條成長(zhǎng)的機(jī)會(huì)。
3.如果你覺得本文的內(nèi)容對(duì)你有幫助,就幫我轉(zhuǎn)發(fā)一下吧。
