Flow
vue框架使用了Flow作為型別檢查,來保證專案的可讀性和維護性。vue.js的主目錄下有Flow的配置.flowconfig檔案,還有flow目錄,指定了各種自定義型別。
在學習原始碼前可以先看下Flow的語法 官方文件
目錄結構
vue.js原始碼主要在src下
src
├── compiler # 編譯相關
├── core # 核心程式碼
├── platforms # 不同平臺的支援
├── server # 服務端渲染
├── sfc # .vue 檔案解析
├── shared # 共享程式碼
compiler
template的編譯
core
core
├── components # 內建元件
├── global-api # 全域性 API 封裝
├── instance # Vue 例項化,生命週期
├── observer # 觀察者,響應式
├── util # 工具函式
├── vdom # virtual DOM
platform
存放2個主要入口,分別打包執行在web和weex上的vue.js
server
支援了服務端渲染
sfc
把.vue檔案內容解析成js物件
shared
存放共享方法
vue.js構建
vue
是基於Rollup
構建的,類似於webpack
首先來看下package.json
檔案,先看下script
欄位:
{
"script":{
"build": "node scripts/build.js",
"build:ssr": "npm run build -- web-runtime-cjs,web-server-renderer",
"build:weex": "npm run build -- weex",
}
}
這3條都是構建vue的命令,後2條是根據需求新增對應環境引數。執行npm run build
時會執行node scripts/build.js
構建過程
構建過程比較複雜,這裡會簡化下構建過程,只分析主線流程
進入到scripts/build.js
,
// 從配置檔案讀取配置,拿到所有構建的path
let builds = require(`./config`).getAllBuilds()
// 過濾builds
build(builds)
再看下配置檔案scripts.config.js
,
let builds= {
`web-runtime-esm`: {
entry: resolve(`web/entry-runtime.js`),
dest: resolve(`dist/vue.runtime.esm.js`),
format: `es`,
banner
},
}
entry
屬性表示構建的入口 JS 檔案地址,dest
屬性表示構建後的 JS 檔案地址。format
屬性表示構建的格式,cjs
表示構建出來的檔案遵循 CommonJS 規範,es
表示構建出來的檔案遵循 ES Module
規範。 umd
表示構建出來的檔案遵循 UMD
規範。
resolve
看下 resovle
方法的定義
const resolve = p => {
const base = p.split(`/`)[0]
if (aliases[base]) {
return path.resolve(aliases[base], p.slice(base.length + 1))
} else {
return path.resolve(__dirname, `../`, p)
}
}
用到了 path.resolve([... paths])
, path.resolve
是 node.js
提供的路徑解析方法,可以看下官方文件瞭解下,主要是從右到左處理給定的路徑序列,直到構造出絕對路徑.
用resolve(`web/entry-runtime.js`)
作分析, base
是 web
, 找到 aliases[base]
即真實路徑 `../src/platforms/web`
,
entry: resolve(`web/entry-runtime.js`)
所以最終入口路徑是 ../src/platforms/web/entry-runtime.js
,構建生成檔案路徑是../dist/vue.runtime.esm.js
genConfig()
輸入builds前要先將builds轉換成rollup打包所對應的配置結構
if (process.env.TARGET) {
module.exports = genConfig(process.env.TARGET)
} else {
exports.getBuild = genConfig
// 返回config組成的陣列
exports.getAllBuilds = () => Object.keys(builds).map(genConfig)
}