1. 程式人生 > >VueCLI3專案的執行全解析-關注細節(一)

VueCLI3專案的執行全解析-關注細節(一)

vue-runtime-analysis(一)

匯出配置檔案

開始分析之前,我們先把專案配置檔案先匯出來,以做分析備用,在VueCLI3配置的文件中可以找到倆中方式找到配置內容:

  • inspect命令:通過下面命令將專案的預設配置匯出到檔案中,這裡命名為preset-default-vue-cli-3.js

     yanyue$ vue inspect > preset-default-vue-cli-3.js
  • vue ui 的inspect面板,點選執行可以獲取到。

    可以通過 vue ui啟動視覺化配置介面 如下圖,在這裡可以看到 task(任務) 面板,task面板有4個task, 選擇inspect面板能夠看到 run(執行按鈕),點選後,便能夠檢視到輸出的配置資訊,在這裡檢視到的是文字方式檢視,由於內容較多,像我這次要分析,需要摺疊程式碼看到這個配置的整體資訊,一般情況,我們不會所有配置都去修改,在這裡查閱非常方便,而且執行一次,下次切換過來這個內容還在。

    單配置檔案1000+行... 從這裡看vue也是花了大功夫把各種配置檔案都放在一起了,並提供統一的修改方式,之後我們會講到如何在專案中修改配置。

clipboard.png

程式入口

main.js

src/main.js是整個程式的入口檔案,在上面匯出的配置檔案中我們搜尋entry這個關鍵字,可以看到下圖的配置資訊:

entry: {
    app: [
        './src/main.js'
    ]
}

VueCLI3專案的入口檔案就是通過該配置欄位來定義輸入給webpack的,最後通過htmlWepackPlugin外掛將打包好的指令碼注入進index.html檔案中。

將vue引入專案

第一行程式碼

import Vue from 'vue'

使用了ES2015的語法將vue的執行時作為依賴模組引入程式。

我們關注一下模組細節

使用VueCLI3安裝的專案,專案的基本依賴(包括babel, vue等)已經被安裝好了,我們去node_modules目錄中找到vue模組目錄,從目錄下package.json檔案能夠看到如下圖:

clipboard.png

從圖中能看到 vue對多種引入方式以不同檔案提供支援,包括符合CommonJS模組規範的 vue.runtime.common.js 、符合ES Module模組規範的vue.runtime.esm.js和符合UMD模組規範的 vue.js以及支援TypeScript的型別定義檔案index.d.ts

我們的專案使用webpack打包各個模組,webpack優先會選取ES模組方式引入包(原因:

webpack中的處理 參考:roollup相關的解釋)

在web環境中,webpack會依據resolve下的mainFields欄位中配置的屬性所指定的位置讀取檔案,而當前版本的vue專案配置中配置了pkg.module和pkg.main這倆個位置,所以webpack優先讀取了module指向的dist/vue.runtime.esm.js檔案,忽略了pkg.main欄位指向的位置檔案。

編譯後的檔案

上面說到了vue.runtime.esm.js這個檔案被webpack作為vue專案提供的vue模組引入到我們的專案中,但是從安裝的vue模組目錄的dist下卻發現了好幾個檔案,如下圖:

clipboard.png

以下大多參考官方文件內容,並做了簡單解釋性翻譯:

解釋編譯後的檔案

Explanation of Build Files

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
Runtime-only (production) vue.runtime.min.js

名詞解釋(Terms)

  • Full: builds that contains both the compiler and the runtime.

    • 完整版,包含 compiler 和 runtime
  • Compiler: code that is responsible for compiling template strings into JavaScript render functions.

    • Compiler : 負責將模板字串編譯成render函式
    • 注意: 請留意下面講到的render函式
  • Runtime: code that is responsible for creating Vue instances, rendering and patching virtual DOM, etc. Basically everything minus the compiler.

    • runtime: 負責建立vue例項, 渲染和調整虛擬DOM等,基本上等效於除去compiler的所有一切。
  • UMD: UMD builds can be used directly in the browser via a <script> tag. The default file from Unpkg CDN at https://unpkg.com/vue is the Runtime + Compiler UMD build (vue.js).

    • UMD檔案可以使用script標籤直接引入html檔案,預設從Unpkg CDN獲取的檔案就是 Runtime + Compiler版本的vue.js檔案
  • : CommonJS builds are intended for use with older bundlers like browserify or webpack 1. The default file for these bundlers (pkg.main) is the Runtime only CommonJS build (vue.runtime.common.js).

    • CommonJS版本為了那些還在使用browserify和webpack1的bundler提供的,預設main入口提供了僅包含Runtime的符合CommonJS規範的版本
  • : ES module builds are intended for use with modern bundlers like webpack 2 or rollup. The default file for these bundlers (pkg.module) is the Runtime only ES Module build (vue.runtime.esm.js).

    • ES模組版本是為了那些現代打包工具像 webpack2+ 或者 rollup,預設module入口提供了僅包含Runtime的符合ES Module規範的版本。

執行時 + 編譯器 與 僅有編譯器 的比較

Runtime + Compiler vs. Runtime-only

If you need to compile templates on the fly (e.g. passing a string to the template option, or mounting to an element using its in-DOM HTML as the template), you will need the compiler and thus the full build.

如果你需要在執行時處理之前編譯templates(例如, 有一個template選項,或者掛載到一個元素上,而你又將元素內的DOM元素作為模板來處理,這時候就需要編譯器這部分進行完整編譯。

When using vue-loader or vueify, templates inside *.vue files are compiled into JavaScript at build time. You don't really need the compiler in the final bundle, and can therefore use the runtime-only build.

如果你打包的時候是用vue-loader 或者 vueify,將`*.vue檔案內的templates編譯成JavaScript程式碼, 你就不需要compiler, 可以使用 runtime-only版本編譯。

Since the runtime-only builds are roughly 30% lighter-weight than their full-build counterparts, you should use it whenever you can. If you wish to use the full build instead, you need to configure an alias in your bundler.

因為僅僅包含執行時編譯比完整版少30%的程式碼體積, 如果你需要使用完整包也是可以的,你需要調整配置。

顯式的改變執行時引用包

Webpack
module.exports = {
  // ...
  resolve: {
    alias: {
      'vue$': 'vue/dist/vue.esm.js' // 'vue/dist/vue.common.js' for webpack 1
    }
  }
}
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"
  }
}

vue模組在引入時做了什麼?

看完了這幾個檔案的用途之後我們再來看看vue引入的時候做了什麼? 帶著這個疑問我們繼續探索。

我們開啟vue.runtime.js檔案,檔案內容有些多,我們先不關注這些細節,我們先看有哪幾大塊功能?

  • 工廠函式,支援不同規範的方式匯出檔案

    clipboard.png

  • 型別檢測定義

    clipboard.png

  • 瀏覽器環境檢測 Browser environment sniffing

    clipboard.png

  • 虛擬DOM的實現定義
  • globals MessageChannel
  • 初始化資料方法定義

    • initState
    • initProps
    • initData
    • initComputed
    • initMethods
    • initWatch
    • initRender
    • initMixin
  • 初始化呼叫

    • initMixin(Vue);
    • stateMixin(Vue);
    • eventsMixin(Vue);
    • lifecycleMixin(Vue);
    • renderMixin(Vue);
  • 這一步vue做了很多的前期準備工作,我們在後面章節還會細化...

本節結束

這一節我們只關注最基礎的這一塊,下一節,我們將繼續關注細節。