【Vue源碼】第一節Flow、Vue源碼目錄設計和Rolluo構建Vue.js源碼

代碼地址:vue2.5.0
參考資料:
- Vue源碼探祕系列
- Vue.js 技術揭祕

Flow

Vue.js 的主目錄下有 .flowconfig 文件, 它是 flow 的配置文件。其中的[libs]用來描述包含指定庫定義的目錄,這裏指向的是項目根目錄下的flow文件夾。打開此目錄,可以發現文件結構如下:

flow
├── compiler.js        # 編譯相關
├── component.js       # 組件數據結構
├── global-api.js      # Global API 結構
├── modules.js         # 第三方庫定義
├── options.js         # 選項相關
├── ssr.js             # 服務端渲染相關
├── vnode.js           # 虛擬 node 相關

Vue源碼目錄設計

在這裏插入圖片描述

  • complier

    ├── compiler    # 模板解析相關
        ├── codegen       # 代碼生成,把 AST(抽象語法樹)轉換爲 render 函數
        ├── directives    # 轉換爲 render 函數前要執行的指令
        ├── parser        # 把模板解析爲 AST
    
  • core

    ├── core        # Vue 核心代碼
        ├── components    # 全局通用組件 Keep-Alive
        ├── global-api    # 全局 api,即 Vue 對象上的方法,如 extend,mixin,use 等
        ├── instance      # Vue 實例化相關代碼,如初始化,事件,渲染,生命週期等
        ├── observer      # 響應式數據修改代碼
        ├── util          # 工具函數
        ├── vdom          # 虛擬 DOM 相關代碼
    
  • platforms

    ├── platforms   # 平臺相關代碼
        ├── web           # web 平臺
            ├── compiler        # 編譯時相關
            ├── runtime         # 運行時相關
            ├── server          # 服務端渲染相關
            ├── util            # 工具函數
        ├── weex          # 配合 weex 運行在 native 平臺
    

Rollup構建Vue

Webpack 功能相比 Rollup 更加強大,它可以將各種靜態資源(包括 cssjs圖片等)通通打包成一個或多個 bundle,並按需加載;同時正因爲 Webpack 功能強大,打包出來的文件體積也較大。因此 Webpack 更適用於應用的開發。而 Rollup 相對於 Webpack 更加輕量,它只處理 js 文件而不處理其他靜態資源文件,打包出來的文件體積也更小,因此 Rollup 更適用於像類庫這種只有 js 代碼的項目構建。所以大部分類庫例如 VueReactAngular 等都採用 Rollup 來打包。

打包vue的命令在package.jsonscript下:

{
  "build": "node scripts/build.js",
  "build:ssr": "npm run build -- web-runtime-cjs,web-server-renderer",
  "build:weex": "npm run build -- weex",
}
  • build 構建 web 平臺相關
  • build:ssr 構建服務端渲染相關
  • build:weex 構建的是 weex 平臺相關。

接下來學習build.js文件:

// scripts/build.js
// 引入所需模塊
const fs = require('fs')
const path = require('path')
const zlib = require('zlib')
const rollup = require('rollup')
const terser = require('terser')

// 檢查是否存在dist目錄,不存在則創建dist目錄
if (!fs.existsSync('dist')) {
  fs.mkdirSync('dist')
}

[1]
let builds = require('./config').getAllBuilds()

[2]
// filter builds via command line arg
if (process.argv[2]) {
  const filters = process.argv[2].split(',')
  builds = builds.filter(b => {
    return filters.some(f => b.output.file.indexOf(f) > -1 || b._name.indexOf(f) > -1)
  })
} else {
  // filter out weex builds by default
  builds = builds.filter(b => {
    return b.output.file.indexOf('weex') === -1
  })
}

build(builds)

// build函數聲明
function build (builds) {
  
}
// scripts/config.js
if (process.env.TARGET) {
  module.exports = genConfig(process.env.TARGET)
} else {
  exports.getBuild = genConfig
  exports.getAllBuilds = () => Object.keys(builds).map(genConfig)
}

[1] 這裏 getAllBuilds 函數的處理是取出 builds 對象的所有屬性組成的數組在 genConfig 函數處理後返回。即把builds裏面的配置對象轉換爲一個Rollup對應需要的配置項並返。
[2] 通過判斷是否有額外的命令參數判斷是那條命令,並對builds數組做對應的過濾處理,把不需要Rollup配置項過濾掉。

最後build 函數其實就是讓 builds 數組每一項都執行 buildEntry 這個函數,這裏 buildEntry 函數調用了 rollup.rollup 進行編譯,最終得到一個結果 output,然後判斷這個 output 是否是生產版本來決定是否壓縮,然後調用 write 函數。write 函數的作用就是調用 fs.writeFile 生成對應的 js 文件放在 dist 目錄下。

總結

學習了flow,vue源碼的編寫依靠flow來進行類型斷言,確保了編譯的嚴謹性;因爲Rollup比webpack輕量,專門打包js,所以vue、react等框架都使用了Rollup;在vue中,通過運行build.js文件,將各個函數處理成rollup對應需要的配置項,且根據不同環境判斷是否要壓縮。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章