看過element-plus的朋友都知道,它在開發階段使用的是unbuild進行的打包編譯。相比較傳統的rollup、webpack等老牌構建工具而言,unbuild更快!!
但這個快並不是指的編譯上更快,畢竟它説到底仍然是基於rollup的,和借力了esbuild的vite相比它並不適合使用更這個修飾詞
這裏的快,指的是次數,和其他構建工具監聽文件變更後reCompile不同,unbuild只在啓動時執行一次
而提供該能力的核心即jiti包
jiti 是做什麼的
jiti是一個npm包,它實現的核心能力即代碼插樁
代碼插樁是指在運行時動態修改代碼的技術
如何啓用
在package.json文件的scripts配置中指定--stub,示例如下
{
"scripts": {
"dev": "unbuild --stub"
}
}
編譯結果如下
import jiti from "jiti這個包對應的系統文件地址";
jiti(...)('目標工程的入口文件');
源碼解析
注意,本文的重點是分析jiti的核心原理,因此對於unbuild不會進行深入探討,同時,既是核心原理,因此對於jiti的實現細節也不在探討範圍
我們關心的是:
1-jiti 是什麼
2-實時編譯是如何實現的
- 首先,jiti 是什麼?
這要從其package.json包開始看起
從框紅的webpack可以知道,它就是一個普通的不能再普通的常規npm包,並沒有使用啥高大上的技術,換言之,它和插樁技術本身毫無關聯
因此,只能從入口找答案,它由main字段標識,指向lib文件夾
{
"main": "./lib/index.js"
}
- 實時編譯是如何實現的
從它是由webpack構建的就可以猜出來,像es語法降級,ts to js轉換這些操作一定是基於wb的某個loader或者plugin實現的,所以這一部分肯定也與插樁技術本身無關
故,去掉編譯相關的邏輯之後,我們很容易就發現瞭如下代碼。顯然,jiti對源代碼創建模塊並重寫了require方法
const mod = new Module(...);
mod.require = createJITI(...);
而createJITI函數,其實就是對模塊的編譯過程,這就做到了,當訪問某個模塊的時候,再進行編譯,即運行時,也即插樁
總結
搞了半天,原來插樁就是個函數重寫😂