由構建讀懂Vue2.0,爲本身的定製實現添磚加瓦!

先簡單介紹一下爲何要研究這個事情的背景,咱們但願能夠基於weex framework.js定製一份本身的實現,weex的融合程度已經到達了Vue的倉庫,學會這個,也有助於摸清楚Vue的脈絡。vue

先從package.json開始,從scripts裏能找出五處跟構建weex有關係的鉤子,分別是:node

"dev:weex": "TARGET=weex-framework rollup -w -c build/config.js", 
"dev:weex:compiler": "TARGET=weex-compiler rollup -w -c build/config.js",    
"build": "node build/build.js",    
"build:weex": "npm run build -- weex-vue-framework,weex-template-compiler",    
"test:weex": "npm run build:weex && jasmine JASMINE_CONFIG_PATH=test/weex/jasmine.json",    
"release:weex": "bash build/release-weex.sh",

無論是dev環境仍是build環境都指向了build/build.js和build/config.js這兩處文件,而release指向了一段shell腳本,先從release開始看看這段腳本有什麼做用:git

set -e
CUR_VERSION=`node build/get-weex-version.js -c`
NEXT_VERSION=`node build/get-weex-version.js`
echo "Current: $CUR_VERSION"
read -p "Enter new version ($NEXT_VERSION): " -n 1 -r
if ! [[ -z $REPLY ]]; then
  NEXT_VERSION=$REPLY
fi
read -p "Releasing weex-vue-framework@$NEXT_VERSION - are you sure? (y/n) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
  echo "Releasing weex-vue-framework@$NEXT_VERSION ..."
  npm run lint
  npm run flow
  npm run test:weex 
  # build
  WEEX_VERSION=$NEXT_VERSION npm run build:weex  
  # update package
  cd packages/weex-vue-framework
  npm version $NEXT_VERSION
  npm publish  cd -  cd packages/weex-template-compiler
  npm version $NEXT_VERSION
  npm publish  cd -  
  # commit
  git add src/entries/weex*
  git add packages/weex*
  git commit -m "[release] weex-vue-framework@$NEXT_VERSION"fi

從脈絡上來看,前面三項的lint flow test都是次要的,主要的是從npm run build:weex開始,看來release也是走到了build/build.js中。web

繼續閱讀build/build.js文件,東西很少,只是一段構建腳本,經過process.argv拿到運行的參數,而後使用rollup來啓動構建。在這個文件中,有這麼一行代碼:let builds = require('./config.js').getAllBuilds(),暫停一下,繼續閱讀build/config.js文件,能夠看到大段的配置信息,找到跟weex相關的有三個,分別是'weex-factory’,'weex-framework’,'weex-compiler’,並且也能夠從entry中找到入口文件,有了入口就比較好辦了。shell

(建議:第一個要學的東西是rollup構建)npm

從構建腳本讀起來,它使用Rollup 構建,起始位置從entries開始,直接載入了weex/framework,在這裏引用vue-runtime(core/index.js),看起來整段腳本使用ES6編寫,並且其內部所引用的都是短路徑,猜想應該是起了別名的,回到build目錄中,能夠看見有alias.js文件,這裏能夠看到不少有用的別名:json

module.exports = {
  vue: path.resolve(__dirname, '../src/entries/web-runtime-with-compiler'),
  compiler: path.resolve(__dirname, '../src/compiler'),
  core: path.resolve(__dirname, '../src/core'),
  shared: path.resolve(__dirname, '../src/shared'),
  web: path.resolve(__dirname, '../src/platforms/web'),
  weex: path.resolve(__dirname, '../src/platforms/weex'),
  server: path.resolve(__dirname, '../src/server'),
  entries: path.resolve(__dirname, '../src/entries'),
  sfc: path.resolve(__dirname, '../src/sfc')
}

(註明:這個比React扁平化的構建方式,更易讀)bash

既然找到了weex framework入口文件,在閱讀這個文件中,找到了幾行關鍵性的代碼,我判斷它應該與定製實現framework有關係。weex

const VueFactory = require('./factory')

在 createVueModuleInstance 函數中的:app

const exports = {}
VueFactory(exports, renderer)
const Vue = exports.Vue

在createInstance函數中的:

Object.freeze(weexInstanceVar)// Each instance has a independent `Vue` mdoule instance
const Vue = instance.Vue = createVueModuleInstance(instanceId, moduleGetter)
const instanceVars = Object.assign({
  Vue,
  weex: weexInstanceVar,    // deprecated
  __weex_require_module__: weexInstanceVar.requireModule // eslint-disable-line
}, timerAPIs)
callFunction(instanceVars, appCode)

這是weex能運行Vue的關鍵之處,那麼其實問題也來,在platforms/weex目錄下並無明顯的./factory 文件,那麼這個是從哪裏來的呢?

(註明:到這裏先暫停一下,無論這個./factory是從哪裏來的,且繼續往下看。)

在createInstance函數中,會執行createVueModuleInstance來掛起Vue的引用,而createVueModuleInstance函數裏,看起來weex團隊用到了Vue.mixin來擴展。

(建議:第二個要學的內容,Vue.mixin是什麼鬼)

而createInstance函數中注入了一個instanceVars,這纔是在Native端weex容器中能真正使用的對象。

(建議:第三個要學的內容,freeze是什麼鬼,assign是什麼鬼)

至此,整個脈絡就比較清晰了,後期考慮好以後咱們能夠很方便的實現定製。

不過,回到上面的VueFactory究竟是什麼?只能從build/build.js文件裏着手了,若是它也是一個構建後的平行「文件」,這個極有可能就是指向vue-runtime.js文件的,(猜想),不過看起來好像還有一些其餘的東西。從release shell腳本處理能夠看出來,它執行了npm run build:weex,而這個npm 鉤子其實是傳入了[ 'weex-vue-framework', 'weex-template-compiler' ]給build/build.js文件,經過這個解析能獲得config.js裏的配置清單,之因此須要傳入一個exports,是由於最後這個VueFactory裏會最終存在exports.Vue = Vue$2來進行交換,這樣,就比較明瞭了。

你們要是對Vue的構建有興趣,也能夠摸着上述的脈絡,閱讀一下,整個庫打包的路徑,對於閱讀源碼,有極大的幫助。

相關文章
相關標籤/搜索