Vue.js 3.x 源碼解析先導

2021-12-29 老黃的前端私房菜
前言

2018 年 6 月我在慕課網發布了 Vue.js 2.x 的源碼解析課程 《Vue.js 源碼全方位深入解析》,同時也開源了課程配套電子書。時隔一年多,Vue 官方也開源了 Vue.js 3.x,那麼在不久的將來,我也會系統化地做 Vue.js 3.x 的源碼分析,同時更新我的這門課程視頻以及電子書。

Vue.js 3.x 源碼剛開源不久,很多人都非常興奮,我也不例外。我寫下這篇文章作為 Vue.js 3.x 源碼解析課程的先導片,和大家聊聊我對 Vue.js 源碼的一些感悟。

聊聊 Vue.js 3.xVue.js 3.x 目前的狀態

Vue.js 3.x 目前處於 Pre-Alpha 的狀態,從 Vue 官方的 Roadmap 來看,2019 年 Q3 結束前開源 Vue 3.x 的源碼,Q4 除了繼續完善 Vue.js 核心源碼之外,還要補齊周邊的生態建設:如 vue-router、vuex、vue-cli、Vue Devtools、JSX 等,在 Q4 結束前才會發布 Alpha 版本。但是 Alpha 版本也只是內部測試版本,之後還要經歷 Beta 對外測試版本,RC 候選發布版本、最後才會到正式的 Realase 版本,所以距離大家在生產環境投入使用還有很長的時間。那麼這段時間,對於 Vue.js 3.x 我可以做哪些事情呢。

Vue.js RFC

Vue.js 官方設立 RFC 的初衷是為了讓 Vue.js 本身的開發流程更加規範化,當有一個新功能的想法出現,會先發布一份 RFC 的提案,由社區在一起討論,當提案通過後再去開發實現。

Vue.js 3.x 在開發之前也發布了多份 RFC 提案,其中討論比較多的是 Vue.js 3.x 關於組件的寫法,由最初的 Class-API 提案被廢棄到之後熱烈討論的 Function-based component API,再到最後確認的基於 Function-based component API 修訂的 Composition API,經歷了很長一段的時間,期間社區出現了不少反對的聲音,比如 「和 React 更像了,為啥我不直接用 React」、「Class API 更好」、「Vue.js 變得一點都不簡單了」 等等,官方都做了很好的回應,因此學習 Vue.js 3.x,你應該先去學習這份 RFC。

通過這份 RFC 的學習,你會大致了解 Vue.js 3.x 組件的寫法、詳細設計、甚至是一些」缺點「。Vue.js 3.x 摒棄了 2.x Options API,擁抱了 Composition API,為了更好的邏輯復用、代碼組織以及更好的類型推導。

Vue.js 3.x 嘗鮮

Vue.js 3.x 源碼已經開放,雖然沒有發布,但是我們可以 clone 下來,安裝好相關依賴,構建一份打包後的代碼為自己所用。

在閱讀完 Composition API 的 RFC 後,我們已經對 Vue.js 3.x 組件的寫法有了一定了解,並且 2.x 的大部分 feature 3.x 都已經支持,我們用 3.x 寫一個簡單的 demo 問題應該不大。我前段時間就基於 Vue 3.x 寫了一個 todomvc 的 demo,感興趣的同學可以去 GitHub  clone 下來跑跑看看。

在寫 demo 的時候我還遇到了 v-model 實現的坑,對源碼一番調試後大致定位了原因,不過由於牽涉到核心的改動會比較多,所以我和尤大反饋了一下(微信提 issue),官方很快就修復了這個問題。

Vue.js 3.x 源碼

Vue.js 3.x 源碼放出來的第二天,社區就有出來源碼分析的文章,不過看了好幾篇都是在分析 Reactive 相關的 API,給人的錯覺好像 Vue 只有響應式一樣,甚至還有某些培訓機構也跟著蹭起了熱度。有些文章寫的還是很不錯的,比如我記得掘金有一篇是教大家從單測看起,確實是一個很好的學習源碼的思路,但還有幾篇也未免有蹭熱度之嫌。對我而言,除了 Reactive,我更願意去關注 Setup 函數的初始化邏輯、Compile 過程的優化、Render 寫法的變化、以及 Patch 過程的優化。

Vue.js 3.x 源碼採用了 monorepo 的管理方式,採用 TypeScript 編寫,對於 Vue.js 的開發者而言,這種方式是更易於維護源碼的。如果你想學習 Vue.js 3.x 的源碼,首先你得學會 TypeScript。

對於大部分人而言,現在去看 Vue.js 3.x 的源碼還為時過早了,主要是你現在還用不到,我之前在掘金髮布過一篇文章來聊聊源碼學習,現在還不是學習 Vue.js 3.x 源碼的好時機。

但是如果你是一個對技術非常有熱情的人,在早期去學習 Vue.js 3.x 源碼,甚至去參與 Vue.js 3.x 的開發共建,對自己的技術提升還是有很大幫助的。

Vue.js 2.x 源碼過時了嗎

Vue.js 3.x 源碼開放了,很多小夥伴不免擔心,我現在學習 Vue.js 2.x 的源碼過時了嗎?

成熟穩定的 Vue.js 2.x

Vue.js 2.x 從 16 年底發布距今已接近 3 年,有無數大廠已經使用 Vue.js 重構和開發項目,Vue.js 2.x 的 npm 下載量每月有 90 多萬,Jsdelivr CDN 每月有 5 億次引用,Chrome DevTools 每周有 90 萬的活躍用戶。如此龐大的用戶量足以說明 Vue.js 是一個非常靠譜和成熟的框架,另外官網對 Issue、Pull Request 的響應也是比較快的,除了高達 97% 的單元測試之外,官方還嘗試做了一些回歸測試。

我們知道 Vue.js 是一個漸進式框架,除了官方提供的一些生態插件 vue-router、vuex、vue-cli 之外,社區還有非常多的優秀的輪子如 element-ui、cube-ui、vue-lazyload、vue-i18n 等,這些插件能很好地輔助我們平時的業務開發。

升級的成本

Vue .js 2.x -> Vue.js 3.x 升級還是有一定的成本的,雖然說官方會出一個保留 Options API 的寫法的版本,但是未免還會有一些 breaking change 的,比如手寫 render 函數部分語法就已經發生了改變,模板寫法也會發生一些變化。未來應該會出一個代碼升級的指南,甚至會用工具幫我們做一部分工作,但是大規模的產線項目做核心框架升級,還是有相當大的成本和風險的。

如果你的業務代碼升級到 Vue.js 3.x,也就意味著你依賴的生態插件也需要升級到 Vue.js 3.x,比如 element-ui 這種大型項目,升級起來也是有相當大的工作量的,所以你需要先等到你依賴的生態插件升級到 Vue.js 3.x 並且穩定後,你才能考慮在你的業務中做框架升級。

Vue.js 1.x -> Vue.js 2.x 的升級似乎沒有那麼麻煩,那是因為 Vue.js 1.x 的時候用戶規模還很小,生態也沒有起來,甚至很多公司直接上手的 Vue.js 2.x,並沒有歷史包袱。

痛點

Vue.js 1.x -> Vue.js 2.x 的升級變化還是很明顯的,虛擬 DOM 在 Vue.js 2.x 中得以實現,它讓服務端渲染、跨端渲染成為可能。我們來看一下 Vue.js 3.x 的設計目標:更小、更快、加強 TypeScript 支持、加強 API 設計一致性、提升自身可維護性、開放更多的底層功能。對大部分用戶而言,更小更快是一個吸引點,對於 TypeScript 用戶而言,加強 TypeScript 支持是一個吸引點,但是這些能解決開發中的痛點麼?

除非  Vue.js 3.x 能解決 Vue.js 2.x 開發中的痛點(比如我這個項目有性能瓶頸,性能的提升能幫助我解決這個性能瓶頸),否則重構的成本和它來帶來的收益就是一個需要權衡的問題。另外考慮到 Vue.js 3.x 用了一些 ES6 的新特性如 Proxy,在瀏覽器兼容性這塊也是需要考慮的。

老闆通常是不會允許你做這種純技術重構的,如果你想用 Vue.js 3.x 做重構,一定要抓到痛點,把重構的收益和老闆說清楚。

雖然老項目用 Vue.js 3.x 重構會有很大的成本和風險,我們也可以在一些非核心的新項目中去嘗試新技術,當然這一切也是需要等待 Vue.js 3.x 正式發布以及依賴的 Vue 插件都更新支持 Vue.js 3.x 才可以。

結論

Vue.js 3.x 想全面替代 Vue.js 2.x 需要有相當長的路要走,未來相當長一段時間 Vue.js 2.x 仍然是主流,Vue.js 2.x 的源碼學習並沒有過時,如果你是一個 Vue.js 2.x 的使用者,就應該去學習 Vue.js 2.x 的源碼。

我應該學習源碼嗎

很多人都有困惑,我會使用不就行了嗎,為什麼還要學習源碼呢?

學習源碼的好處

學習是為了更好的工作,工作中難免會遇到一些問題,學習源碼最直接的好處是能幫你直接定位問題的根本原因,從而幫助你解決問題。很多人抱怨加班多,不妨問問自己,有多少時間是在寫業務,多少時間是在寫(找) bug。快速定位問題解決 bug,可以有效地提升你的工作效率,很可能就不用加班了,甚至會多出學習的時間,形成一個良性循環。

學習源碼可以很好地鞏固基礎,修煉內功,提升技術。前端幾乎都會學習 JS 的基礎知識,如類型、變量、函數、作用域、閉包、原型鏈、event loop 等知識,但很多人很難把這些知識在實踐中運用自如,主要原因還是實踐的少了,大部分時間都在寫業務的膠水代碼。學習 Vue.js 這類框架的源碼,會不斷去鞏固這些知識點,如果你源碼看熟練了,那麼你的 JS 基礎就會更紮實。

學習源碼有助於你更好地理解所用的技術棧,更熟練地在工作中運用。比如你深入學習了 Vue.js 的核心源碼,你會理解 Vue.js 框架產生的意義、Vue.js 的職責邊界、數據驅動的本質;你還會知道如何實現的組件化,在什麼生命周期應該做什麼事情,如何編寫 Vue.js 的插件,如何和其它第三方 JS 庫深度結合。你再也不會問「如何用 Vue 實現 XXX」 的傻問題了。

學習源碼可以讓我們站在巨人的肩膀上,Vue.js 這麼優秀,尤大也是參考了很多其他優秀源碼的實現,比如 Vue.js 2.x  Virtual DOM 部分參考了 snabbdom,Vue.js 3.x Reactive 的實現參考了Meteor Tracker 和 salesforce/observable-membrane 等。我們在閱讀的源碼的時候,也可以把源碼中的優秀的設計思想、代碼實現吸納到我們平時的開發工作中。

學習源碼還有一個偏功利的作用,應付面試。越來越多的公司在面試環節會考察候選人對所用技術棧實現原理的考察,主要目的還是考察候選人的技術能力以及技術熱情和追求,因為通常對技術熱愛的人通常都會保持技術好奇,樂於探究所用到的技術棧的實現原理。但是往往以這個目的去學習源碼的同學是學不好的,對源碼的理解很淺,甚至出現了死記硬背的情況。所以學習好源碼可以幫助我們在面試中應答自如,但是我們不應該為了面試去學習源碼。

學源碼的時機

通常我們去學習一個技術棧的源碼的時機是在我們對他的使用已經很熟練的情況,比如你是一個 Vue.js 的一年以上經驗的使用者,那麼你已經可以去學習它的源碼了,這時候你的學習應該是系統化地學習。

當你工作中使用某一個新框架的時候遇到一個奇怪的問題,通過查閱文檔也未能解決,這個時候你也可以去看源碼,當然這個時候並不需要系統地去學習,只需要把和你問題相關的源碼理解了,找到問題即可。當然想達到這一步就需要你有快速閱讀源碼定位問題的能力,這個能力也是在你不斷去閱讀大量優秀源碼過程中鍛鍊的。

學不動了怎麼辦

源碼學習的好處我們已經介紹了很多,但是源碼學習的本身是枯燥的,抽象的,它沒有直觀酷炫的效果,學習起來費腦子,是很多人直呼學不動的原因。

其實學不動的主要原因還是因為沒掌握好的學習方法,好的方法能讓你事半功倍,正如我在來聊聊源碼學習 文章中提到的幾個方法,全盤了解、問題驅動、主線優先、參與共建、閱讀技巧、輔助資料。除了這些方法,根據我源碼課程中一些學的不錯的同學的經驗,自己在學習的過程中多記筆記,多在課程問答區提問,甚至最後自己產出源碼分析系列文章,都能非常好的輔助學習源碼。其實做這些事情都是不斷在幫助自己建立自信和成就感,激發學習興趣,把無趣的事情變得有趣和有意義。

課程後續計劃

源碼課程會等待 Vue.js 3.x 發布正式版本且穩定後會開始準備重新錄製,仍然是電子書和視頻的方式。

重新錄製的源碼課程不僅僅會講清楚源碼實現流程,還會多加入一些使用場景、設計原因的分析。

翻新課程是在原課程的基礎上增加 Vue.js 3.x 的章節,已購買課程的同學可以繼續學習,無需購買新課程。

先學會用再學原理,因此在 Vue.js 3.x 正式發布後,我會優先重新錄製 《Vue2.0開發企業級移動端音樂Web App》課程,同樣是免費升級喔。

音樂課程 + 源碼課程的重新錄製,是我明年的主要計劃,暫無計劃出新課程了。除了版本的升級,我會像《Vue.js2.5 + cube-ui重構餓了麼App》升級課程那樣儘量往課程中加入一些新東西的,敬請期待~

相關焦點

  • Vue-Router源碼學習之index.js(vue-router類)
    今天,帶來Vue-Router源碼解析系列的第二篇文章:index.js。正文vue-router類裡面都做了什麼?index.js是vue-router這個類的主構造函數,所以內容上算是比較關鍵的:從圖片中我們可以看出來,這是一個ES6聲明類的方法,vue-router源碼中類的聲明都是使用類ES的語法,constructor (options: RouterOptions
  • Vue3 知名組件庫 NaiveUI 源碼揭秘
    理解高潮 MVP其次我們看源碼要有一定的技巧,複雜如 React[3],可以算作一個簡單的作業系統了,如果你上來通過比較簡單粗暴的從代碼入口開始,一路打斷點了解源碼,那你再怎麼堅持也會想吐的。對於那些非葉子依賴,我們需要再下一番功夫繼續解析其依賴,重複之前的兩項操作:刪除 TS 或者其他和 Button 不相干的代碼和依賴最後就是對照著源碼的目錄結構創建一樣的結構,將處理完無關內容的代碼拷貝過去。
  • JS每日一題: 簡述一下Vue.js的template編譯過程?
    name"    },    "children": [      {        "data": "JS每日一題",        "type": "text",        "next": null,        "startIndex": 18,        "prev":
  • Vue面試題(3)Vue-Router和Vuex
    Vuex 是一個專為 Vue.js 應用程式開發的狀態管理模式。每一個 Vuex 應用的核心就是 store(倉庫)。「store」 基本上就是一個容器,它包含著你的應用中大部分的狀態 ( state )。(1)Vuex 的狀態存儲是響應式的。當 Vue 組件從 store 中讀取狀態的時候,若 store 中的狀態發生變化,那麼相應的組件也會相應地得到高效更新。
  • 使用 Vue.js 和 Vuex 實現購物車場景
    Flux-inspired Application Architecture for Vue.jsVuex 實際上是類Flux的數據管理架構。它主要幫我們更好的組織代碼,更好的讓 Vue 中的狀態更好的通過狀態管理維護起來。
  • Vue.js 框架第三版源碼公布
    10 月 5 日凌晨,Vue.js 框架的作者兼核心開發者尤雨溪公布了尚處於 Pre-Alpha 狀態的 Vue 3 源碼(https://github.com
  • 淺析 vue-router 源碼和動態路由權限分配
    vue-router 源碼分析首先閱讀源碼之前最好是將 Vue 和 vue-router 的源碼克隆下來,然後第一遍閱讀建議先跟著 官方文檔 (https://router.vuejs.org/zh/) 先走一遍基礎用法,然後第二遍開始閱讀源碼,先理清楚各層級目錄的作用和抽出一些核心的文件出來,過一遍代碼的同時寫個小的
  • 從頭開始學習Vuex
    在搭建下面頁面時,你可能會對 vue 組件之間的通信感到崩潰 ,特別是非父子組件之間通信。此時就應該使用vuex,輕鬆可以搞定組件間通信問題。二、什麼是VuexVuex 是一個專為 Vue.js 應用程式開發的狀態管理模式。它採用集中式存儲管理應用的所有組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。這裡的關鍵在於集中式存儲管理。
  • Vue 新版腳手架工具,300 行代碼輕盈新生!
    前言想學源碼,極力推薦之前我(若川)寫的《學習源碼整體架構系列》 包含jQuery、underscore、lodash、vuex、sentry、axios、redux、koa、vue-devtools、vuex4、koa-compose、vue-next-release、vue-this等十餘篇源碼文章。
  • 【項目推薦】Vue.js
    作者是尤雨溪,寫下這篇文章時 vue.js版本為 1.0.7 。我推薦使用 sublime text 作為編輯器,關於這個編輯器可以看我這篇文章。 </div> </div> </div></body></html>當然你也可以在 github 上 clone 最新的版本並作為單文件引入,或者使用 CDN:http://cdn.jsdelivr.net/vue/1.0.7/vue.min.js
  • 【Vue.js 入門到實戰教程】01-Vue.js 數據綁定的基本實現和代碼分析
    註:本系列教程依然基於 Vue 2.x,使用的代碼編輯器是 IntelliJ IDEA,你可以按照自己的喜好選擇代碼編輯器,比如 WebStorm、PhpStorm、VS Code、Sublime Text 等。
  • Vue.js 框架作者公布 Vue 3 最新進展
    Vue.js 作者尤雨溪近日介紹了 Vue 3 的最新進展。Vue Router目前存在部分與 vue-router@3.x 相關的路由鉤子 (router hook)行為一致性問題,這也是 Vue Router 沒有被標記為 Beta 的原因。不過在非關鍵項目上可以使用新的路由。
  • 進階| Vue 2.x + Webpack 3.x + Nodejs 多頁面項目框架(下篇)
    稍微詳細的信息,大家可以參考:官網:https://ssr.vuejs.org/zh/還有官方的例子:https://github.com/vuejs/vue-hackernews-2.0不過,文檔寫得並不詳細,也沒看到文檔對應的代碼在哪裡;而例子呢,下載後無法運行(2017年12月上旬),也是有點麻煩。
  • 搭建 Vue CLI 4.x + Webpack5 + Vue 3.x 移動端框架
    搭建 Vue CLI 4.x + Webpack5 + Vue 3.x 移動端框架一、技術棧這是基於 Vue CLI4 實現的移動端框架,其中包含常用的配置技術選型:Vue CLI4 + Webpack5 + JavaScript(不上Ts)+ Vue 3.x + Vue Router 4.x + Vuex 4.x + Less + Vant-ui + rem適配 + eslint + husky
  • Vue造輪子必備*.vue文件源碼讀取並高亮展示
    前言(需求)就是想讀取 *.vue 文件的源碼並高亮展示到頁面上,又不想用第三方的依賴(其實是找不到)。2.實現思路通過  vue-loader 自定義塊 功能,獲取目標文件的文件路徑,然後通過 fs 讀取源碼,再用 @vue/compiler-core 的 API baseParse將讀取到的內容轉換成 AST 語法抽象樹,然後將 fs 讀取的內容中 抽離出 自定義塊內容 和 需要的源碼,最後再將以上兩個內容重新掛到組件對象上,直接讀取組件相應的欄位就可以
  • Vue Element+Node.js開發企業通用管理後臺系統
    5-1 element-ui基本用法5-2 element-ui按需加載5-3 element-ui插件引用5-4 表單的基本用法5-5 表單校驗的基本用法5-6 表單校驗的高級用法5-7 表單常見屬性解析5-8 el-form源碼解析第6章 Vuex和Vue-router進階對Vue的全家桶中兩個重要插件:Vuex
  • Vue.js系列之vue-router(上)(3)
    說明:我們項目現在用的是:vue2.0 + vue-cli + webpack + vue-router2.0 + vue-resource1.0.3
  • Vue.js 3.0 "One Piece" 正式版發布
    Vue.js 3.0 正式版發布的內容為英文版本,原文見:https://github.com/vuejs/vue-next/releases。今天,我們非常自豪地宣布 Vue.js 3.0 "One Piece" 發布。
  • Vue.js 2.5 發布,而這個會玩的團隊已經自研出用 Vue 開發小程序的...
    注意:TypeScript 用戶還應將以下包更新為最新版本從而兼容類型聲明:vue-router,vuex,vuex-router-sync 和vue-class-component。更好地錯誤處理在2.4及更早版本中,我們通常使用全局 config.errorHandleroption 來處理應用程式中的意外錯誤。
  • Vuex 4源碼學習筆記 - mapState、mapGetters、mapActions等輔助函數原理(六)
    注意:這幾個函數並不能使用在Vue3的Compositon API中,一會從下面的代碼我們就可以看到,這幾個輔助函數內都用到了this來訪問當前的組件實例,而在Setup中,this還沒有被創建,所以不能使用這些輔助函數。