Vue 原始碼解讀(1)—— 前言

李永寧發表於2022-02-21

當學習成為了習慣,知識也就變成了常識。 感謝各位的 點贊收藏評論

新視訊和文章會第一時間在微信公眾號傳送,歡迎關注:李永寧lyn

文章已收錄到 github 倉庫 liyongning/blog,歡迎 Watch 和 Star。

簡介

專欄的第一篇,主要介紹專欄的目的、規劃、適用人群,以及準備工作和掃盲的基礎知識。

前言

最近在準備一些 Vue 系列的文章和視訊,之前 Vue 的原始碼也讀過好幾遍,但是一直沒寫相關的文章,所以最近就計劃寫一寫。

目標

精通 Vue 技術棧的原始碼原理,這是這系列的文章最終目的。

首先會從 Vue 原始碼解讀開,會產出一系列的文章和視訊,從詳細刨析原始碼,再到 手寫 Vue 1.0Vue 2.0。之後會產出周邊生態相關庫的原始碼分析和手寫系列,比如:vuex、vue-router、vue-cli 等。

相信經過這一系列的認真學習,大家都可以在自己的簡歷上寫上這麼一條:精通 Vue 技術棧的原始碼原理

適合人群

  • 熟練使用 Vue 技術棧進行日常開發(增刪改查)

  • 想深入瞭解框架實現原理

  • 想跳槽 或 跟老闆提漲薪的同學(增刪改查不值錢)

如何學習

對於系列文章,順序學習自然最好,但如果你本身對原始碼有一些瞭解或者對某一部分特別感興趣,也可以直接看相應對應的文章。

很多人習慣利用碎片化時間去學習,對於快餐類的文章當然沒有問題,但是如果你想深入學習,還是建議坐在電腦前用整塊的時間對照著文章親自動手去學。

記住:光看不練假把式,所以在學習過程中一定要勤動手,不動筆墨不讀書,像筆記、思維導圖、示例程式碼、為原始碼編寫註釋、debug 除錯等,該上就上,絕對不能偷懶。

如果你覺得該系列文章對你有幫助,歡迎大家 點贊關注,也歡迎將它分享給你身邊的小夥伴。

準備

現在最新的 Vue 2 的版本號是 2.6.12,所以我就以當前版本的程式碼進行分析和學習。

下載 Vue 原始碼

  • git 命令
git clone https://github.com/vuejs/vue.git
  • github 手動下載然後解壓

裝包

執行 npm i 安裝依賴,待裝到端到端測試工具時可直接 ctrl + c 掉,不影響後續原始碼的研讀。

source map

在 package.json -> scripts 中的 dev 命令中新增 --sourcemap,這樣就可以在瀏覽器中除錯原始碼時檢視當前程式碼在原始碼中的位置。

{
  "scripts": {
    "dev": "rollup -w -c scripts/config.js --sourcemap --environment TARGET:web-full-dev"
  }
}

開發除錯

執行以下命令,啟動開發環境:

npm run dev

看到如下效果,並在 dist 目錄下生成 vue.js.map 檔案,則表示成功。到這裡所有的準備工作均已完成,但是不要將當前命令列 ctrl + c 掉,因為你在閱讀原始碼時會需要向原始碼中新增註釋,甚至改動原始碼,當前命令可以監測原始碼的改動,如果發現改動會自動進行打包;如果關閉當前命令列,你會發現,隨著你註釋程式碼的編寫,在瀏覽器中除錯原始碼時會出現和原始碼對映的偏差。所以為了更好的除錯體驗就別關閉它。

掃盲

執行 npm run build 命令之後會發現在 dist 目錄下生成一堆特殊命名的 vue.*.js 檔案,這些特殊的命名分別是什麼意思呢?

構建檔案分類

UMD CommonJS ES Module
Full vue.js vue.common.js vue.esm.js
Runtime-only vue.runtime.js vue.runtime.common.js vue.runtime.esm.js
Full (production) vue.min.js vue.common.prod.js
Runtime-only (production) vue.runtime.min.js vue.runtime.common.prod.js

名詞解釋

  • Full:這是一個全量的包,包含編譯器(compiler)和執行時(runtime)。

  • Compiler:編譯器,負責將模版字串(即你編寫的類 html 語法的模版程式碼)編譯為 JavaScript 語法的 render 函式。

  • Runtime:負責建立 Vue 例項、渲染函式、patch 虛擬 DOM 等程式碼,基本上除了編譯器之外的程式碼都屬於執行時程式碼。

  • UMD:相容 CommonJS 和 AMD 規範,通過 CDN 引入的 vue.js 就是 UMD 規範的程式碼,包含編譯器和執行時。

  • CommonJS:典型的應用比如 nodeJS,CommonsJS 規範的包是為了給 browserify 和 webpack 1 這樣舊的打包器使用的。他們預設的入口檔案為 vue.runtime.common.js

  • ES Module:現代 JavaScript 規範,ES Module 規範的包是給像 webpack 2 和 rollup 這樣的現代打包器使用的。這些打包器預設使用僅包含執行時的 vue.runtime.esm.js 檔案。

執行時(Runtime)+ 編譯器(Compiler) vs. 只包含執行時(Runtime-only)

如果你需要動態編譯模版(比如:將字串模版傳遞給 template 選項,或者通過提供一個掛載元素的方式編寫 html 模版),你將需要編譯器,因此需要一個完整的構建包。

當你使用 vue-loader 或者 vueify 時,*.vue 檔案中的模版在構建時會被編譯為 JavaScript 的渲染函式。因此你不需要包含編譯器的全量包,只需使用只包含執行時的包即可。

只包含執行時的包體積要比全量包的體積小 30%。因此儘量使用只包含執行時的包,如果你需要使用全量包,那麼你需要進行如下配置:

webpack

module.exports = {
  // ...
  resolve: {
    alias: {
      'vue$': 'vue/dist/vue.esm.js'
    }
  }
}

Rollup

const alias = require('rollup-plugin-alias')

rollup({
  // ...
  plugins: [
    alias({
      'vue': 'vue/dist/vue.esm.js'
    })
  ]
})

Browserify

Add to your project's package.json:

{
  // ...
  "browser": {
    "vue": "vue/dist/vue.common.js"
  }
}

原始碼目錄結構

通過目錄結構的閱讀,對原始碼有一個大致的瞭解,知道哪些東西需要去哪看。

├── benchmarks                  效能、基準測試
├── dist                        構建打包的輸出目錄
├── examples                    案例目錄
├── flow                        flow 語法的型別宣告
├── packages                    一些額外的包,比如:負責服務端渲染的包 vue-server-renderer、配合 vue-loader 使用的的 vue-template-compiler,還有 weex 相關的
│   ├── vue-server-renderer
│   ├── vue-template-compiler
│   ├── weex-template-compiler
│   └── weex-vue-framework
├── scripts                     所有的配置檔案的存放位置,比如 rollup 的配置檔案
├── src                         vue 原始碼目錄
│   ├── compiler                編譯器
│   ├── core                    執行時的核心包
│   │   ├── components          全域性元件,比如 keep-alive
│   │   ├── config.js           一些預設配置項
│   │   ├── global-api          全域性 API,比如熟悉的:Vue.use()、Vue.component() 等
│   │   ├── instance            Vue 例項相關的,比如 Vue 建構函式就在這個目錄下
│   │   ├── observer            響應式原理
│   │   ├── util                工具方法
│   │   └── vdom                虛擬 DOM 相關,比如熟悉的 patch 演算法就在這兒
│   ├── platforms               平臺相關的編譯器程式碼
│   │   ├── web
│   │   └── weex
│   ├── server                  服務端渲染相關
├── test                        測試目錄
├── types                       TS 型別宣告

連結

感謝各位的:點贊收藏評論,我們下期見。


當學習成為了習慣,知識也就變成了常識。 感謝各位的 點贊收藏評論

新視訊和文章會第一時間在微信公眾號傳送,歡迎關注:李永寧lyn

文章已收錄到 github 倉庫 liyongning/blog,歡迎 Watch 和 Star。

相關文章