通過軟件框架閱讀源碼可以對框架本身運行機制進行學習,更能了解框架的API設計、原理及流程、設計思路;我們要知其然,更知其所以然。
Vue 3的源碼相對于Vue 2版本有了較大程度的改變,采用Monorepo規范的目錄結構,同時使用TypeScript作為開發語言(vue2在2022年4月底也更換TypeScript為開發語言 ),并添加了很多新的特性和優化。
1. 下載&啟動Vue3源碼
2023-03-31最新版本為V3.3.0-alpha.5
git clone https://github.com/vuejs/core.git
下載完成后進入core文件夾,由于vue3源碼采用Yarn構建,我們還要先安裝下Yarn
npm i yarn -g
然后安裝相關依賴
yarn --ignore-scripts
可用npm run dev
開啟源碼調試模式,完整的源代碼目錄結構如下圖
core
├─ packages
│ ├─ compiler-core // 核心編譯器
│ ├─ compiler-dom // dom編譯器
│ ├─ compiler-sfc // vue單文件編譯器
│ ├─ compiler-ssr // 服務端渲染編譯
│ ├─ dts-test //測試Typescript類型以確保類型保持為預期類型
│ ├─ global.d.ts // TypeScript聲明文件
│ ├─ reactivity // 響應式模式,可以和其它框架配合使用
│ ├─ reactivity-transform // 該功能現在被標記為不推薦使用,并將從Vue核心中刪除,提案已經被放棄。
│ ├─ runtime-core // 運行時核心實例相關代碼
│ ├─ runtime-dom // 運行時dom相關API、屬性、事件處理
│ ├─ runtime-test // 運行時測試相關代碼
│ ├─ server-renderer // 服務器渲染
│ ├─ sfc-playground // 單文件組件在線調試器
│ ├─ shared // 內部工具庫,不對外暴露
│ ├─ size-check // 測試代碼體積
│ ├─ template-explorer // 用于調試編譯器輸出的開發工具
│ ├─ vue //面向公眾的完整版本,包含運行時和編譯器
│ └─ vue-compat //是Vue 3的一個構建,它提供了可配置的Vue 2兼容行為。
2. 目錄模塊
compiler-core、compiler-dom、runtime-core、runtime-dom這幾個模塊比較重要。
compile:可以理解為程序編譯時,是指我們寫好的源代碼在被編譯成為目標文件這段時間,在這里可以理解為我們將.vue文件編譯成瀏覽器能識別的.js文件的一些工作。
runtime:可以理解為程序運行時,即程序被編譯了之后,在瀏覽器打開程序并運行它,直到程序關閉的這段時間的系列處理。
reactivity目錄也比較重要,它是響應式模塊的源碼,由于Vue 3整體源碼采用的是Monorepo(單體倉庫)規范,因此其下面每個子模塊都可以獨立編譯和打包,從而獨立對外提供服務,在使用時采用require('@vue/reactivity')引入,進入reactivity目錄下可以看到有對應的package.json文件。
3. 構建版本
可以通過以下命令進行構建,構建出Vue 3所有的版本
npm run build
構建好的文件在目錄: core\packages\vue\dist ,說明如下:
// cjs(用于服務端渲染)
vue.cjs.js
vue.cjs.prod.js(生產版,代碼進行了壓縮)
// global(用于瀏覽器<script src="" />標簽導入,導入之后會增加一個全局的Vue對象)
vue.global.js
vue.global.prod.js(生產版,代碼進行了壓縮)
vue.runtime.global.js
vue.runtime.global.prod.js(生產版,代碼進行了壓縮)
// browser(用于支持ES 6 Modules瀏覽器<script type="module" src=""/>標簽導入)
vue.esm-browser.js
vue.esm-browser.prod.js(生產版,代碼進行了壓縮)
vue.runtime.esm-browser.js
vue.runtime.esm-browser.prod.js(生產版,代碼進行了壓縮)
// bundler(這兩個版本沒有打包所有的代碼,只會打包使用的代碼,需要配合打包工具來使用,會
讓Vue體積更小)
vue.esm-bundler.js
bue.runtime.esm-bundler.js
也可通過以下命令選擇性構建,具體的-f參數以及其他參數配置的含義可以在core/rollup.config.js里面找到。
# 構建運行時版本 vue.runtime.global.js
node scripts/dev.js -f global-runtime
# 構建出完整版,vue.global.js
node scripts/dev.js -f global
如果需要在客戶端編譯模板(即將字符串傳遞給template選項,或者使用元素的DOM內的HTML作為模板掛載到元素),則需要編譯器,因此需要完整的構建版本,代碼如下:
// 需要編譯器
Vue.createApp({
template: '<div>{{ hi }}</div>'
})
// 不需要
Vue.createApp({
render() {
return Vue.h('div', {}, this.hi)
}
})
當使用Webpack的vue-loader時,.vue文件中的模板會在構建時預編譯為JavaScript,在最終的捆綁包中并不需要編譯器,因此可以只使用運行時構建版本。所以,如果直接在瀏覽器打開Vue的頁面,則可以直接采用<script>引入完整版本,如果采用構建工具(例如Webpack)進行構建,則可以使用import引入運行時版本,和構建相關的腳本源碼都在core/scripts下面。