深入解析vue 源碼目錄及構(gòu)建過程分析
“ 本文主要梳理一下vue代碼的目錄,以及vue代碼構(gòu)建流程,旨在對(duì)vue源碼整體有一個(gè)認(rèn)知,有助于后續(xù)對(duì)源碼的閱讀?!?/p>
一、目錄結(jié)構(gòu)
上圖是對(duì)vue的代碼的所有目錄進(jìn)行的梳理,其中源碼位于src目錄下,下面對(duì)src下的目錄進(jìn)行介紹。
compiler
該目錄是編譯相關(guān)的代碼,即將 template 模板轉(zhuǎn)化成 render 函數(shù)的代碼。
vue 提供了 render 函數(shù),render 函數(shù)作用是用來創(chuàng)建 VNode,但在平時(shí)開發(fā)中,絕大多數(shù)情況下使用 template 來創(chuàng)建 HTML,所以需要將 template模板編譯成 render 函數(shù)。
編譯工作既可以在代碼構(gòu)建時(shí)做,也可以在客戶端運(yùn)行時(shí)做,但編譯十分消耗性能,所以在項(xiàng)目中建議使用 runtime 版本。
core
這部分代碼是 vue 的核心代碼,可以說是 vue 的靈魂所在,也是我們要重點(diǎn)學(xué)習(xí)的源碼。
core目錄又包含如下子目錄。
•components -- 內(nèi)置組件的代碼,即 keep-alive 代碼
•global-api -- 全局API代碼,mixin,extend 等 api 在這里實(shí)現(xiàn)
•instance -- vue實(shí)例化相關(guān)代碼,包括初始化,事件,生命周期,渲染等部分的代碼
•observer -- 響應(yīng)式數(shù)據(jù)相關(guān)代碼
•util -- 工具方法
•vdom -- 虛擬 dom 的代碼。
platforms
platforms下包含兩個(gè)子目錄,web 和 weex。
分別代表可以打包生成在web端使用的 vue 代碼和在native端使用的 weex 代碼。美團(tuán)開源的開發(fā)微信小程序的 mpvue 框架也是在這個(gè)目錄下進(jìn)行拓展的。
通過不同平臺(tái)的入口就可以打包出運(yùn)行在不同平臺(tái)的版本的 vue 文件,后面代碼構(gòu)建部分會(huì)介紹具體的構(gòu)建過程。
server
該目錄下是 SSR 相關(guān)的代碼。
Vue.js 是構(gòu)建客戶端應(yīng)用程序的框架。除了可以在瀏覽器中輸出 Vue 組件,也可以將同一個(gè)組件渲染為服務(wù)器端的 HTML 字符串,將它們直接發(fā)送到瀏覽器,最后將這些靜態(tài)標(biāo)記"激活"為客戶端上完全可交互的應(yīng)用程序。
sfc
我們平時(shí)開發(fā)時(shí),都是寫 .vue 文件。sfc 的代碼就是提供一個(gè)解析器,把.vue文件代碼解析成一個(gè) javascript 對(duì)象。
shared
該目錄下定義了一些公用的工具方法,提供給上面的幾個(gè)目錄內(nèi)代碼使用。
二、源碼編譯
vue的源碼按照功能拆分的十分清晰,每個(gè)功能都有單獨(dú)的目錄,那么項(xiàng)目中引用的vue文件是怎么編譯出來的呢?
首先,我們看一下編譯輸出的dist目錄。
可以看到,dist下有10幾種不同版本的vue文件,他們是根據(jù)不同規(guī)范(包括 CommonJS規(guī)范,ES Module,UMD)和 是否包含編譯器 構(gòu)建出的不同版本。
vue源碼選擇了rollup進(jìn)行構(gòu)建,rollup相比于webpack,更加輕量,編譯后的代碼更加干凈,更適合javascript庫的構(gòu)建,除了vue以外,像React,Ember,D3,Three.js 以及其他很多開源庫也選擇了Rollup 進(jìn)行構(gòu)建。
下面看一下vue具體構(gòu)建過程,首先到pakage.json中看下vue編譯執(zhí)行的命令。
從命令可以看出,構(gòu)建命令就是執(zhí)行 scripts 目錄下 build.js 文件。
下面是 scripts/build.js 核心代碼(下文中漢字注釋部分是為方便理解自己補(bǔ)充的)
從代碼可以看出,首先通過 script/config.js 文件的getAllBuilds方法獲取配置,然后根據(jù)構(gòu)建命令傳入的參數(shù)對(duì)配置進(jìn)行過濾,最后根據(jù)過濾后的配置執(zhí)行build函數(shù),編譯出對(duì)應(yīng)版本的vue文件。(這里介紹代碼構(gòu)建的過程,主要說明vue是怎么構(gòu)建出不同版本代碼的,build方法在此不做分析)
接下來我們在看一下配置文件 script/config.js 中的 getAllBuilds 是怎么獲取具體配置的。
可以看出,getAllBuilds 方法首先通過 Object.keys 拿到 builds 對(duì)象所有key的組成的數(shù)組,并通過map遍歷執(zhí)行g(shù)enConfig方法。下面我們先看一下builds對(duì)象。
可以看出,builds對(duì)象是不同版本vue的編譯配置。具體配置項(xiàng)的作用,已經(jīng)用注釋在代碼中標(biāo)出。接下來我們看下genConfig函數(shù)做了什么。
genConfig 通過 key 拿到 builds 中每個(gè)key對(duì)應(yīng)的配置對(duì)象,然后根據(jù)這個(gè)對(duì)象重新定義一個(gè) config 對(duì)象,這個(gè) config 對(duì)象的結(jié)構(gòu)才是 rollup 配置真正需要的結(jié)構(gòu)。
看了 builds 對(duì)象和 genConfig 方法,我們就知道了 getAllBuilds 的目的,是通過映射把 builds 配置對(duì)象轉(zhuǎn)化成 rollup 所需要的配置數(shù)據(jù)。
到這里,我們就清楚是如何構(gòu)建出不同版本的vue代碼了。
三、心得
學(xué)習(xí)源碼時(shí),不建議按照源碼的順序一行一行的閱讀。首先要抓住主干,先梳理清楚主要的代碼邏輯,再去仔細(xì)閱讀具體的每行代碼。另外按照源碼順序閱讀可能很枯燥,很難堅(jiān)持下來,可以先選擇自己感興趣的部分進(jìn)行學(xué)習(xí),最后再串聯(lián)起來。
相關(guān)文章
vue-cli2 構(gòu)建速度優(yōu)化的實(shí)現(xiàn)方法
這篇文章主要介紹了vue-cli2 構(gòu)建速度優(yōu)化的實(shí)現(xiàn)方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-01-01尤雨溪開發(fā)vue?dev?server理解vite原理
這篇文章主要為大家介紹了尤雨溪開發(fā)的玩具vite,vue-dev-server來理解vite原理,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07vue使用swiper的時(shí)候第二輪事件不會(huì)觸發(fā)問題
這篇文章主要介紹了vue使用swiper的時(shí)候第二輪事件不會(huì)觸發(fā)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09詳解vuex數(shù)據(jù)傳輸?shù)膬煞N方式及this.$store undefined的解決辦法
這篇文章主要介紹了vuex數(shù)據(jù)傳輸?shù)膬煞N方式 及 this.$store undefined的解決辦法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08Vue異步更新DOM及$nextTick執(zhí)行機(jī)制解讀
這篇文章主要介紹了Vue異步更新DOM及$nextTick執(zhí)行機(jī)制解讀,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03