衆所周知,taro-cli
是Taro腳手架初始化和項目構建的的命令行工具,它的實現原理,相信你們從Taro 技術揭祕:taro-cli這篇文章中已經有所瞭解;本文將對其中的項目構建build
命令進行分析,從cli
層面瞭解taro
構建的過程到底作了什麼;前端
在執行npm install -g @tarojs/cli
時,npm
經過讀取package.json
文件中的bin
字段,將taro
這個命令註冊到[prefix]/bin
中做爲全局命令;
若是在當前項目目錄下,執行npm install @tarojs/cli
,則會將taro這個命令註冊到./node_modules/.bin/
底下做爲本地命令;node
// package.json "bin": { "taro": "bin/taro" }
因爲npm config get prefix
爲/usr/local
,因此全局命令將會被註冊到/usr/local
目錄底下,經過symlink
符號連接的方式,使得/usr/local/bin/taro
指向/usr/local/lib/node_modules/@tarojs/cli/bin/taro
; webpack
bin/taro
文件做爲taro-cli
的入口,內部使用commander.js
來解析命令中的參數,而且支持git
風格的子命令處理,能夠根據子命令自動引導到[command]-[subcommand]
格式命名的執行文件; git
因此當執行taro build
命令時,則被commander.js
自動引導到bin/taro-build
文件下,繼而執行bin/taro-build
的邏輯;es6
taro build
命令功能很是多,它可以支持:web
H5
;taro build --type h5
weapp/swan/alipay/tt/qq/jd
類型;// 小程序 taro build --type weapp // 小程序插件 taro build --plugin weapp
cross-env TARO_BUILD_TYPE=component taro build --ui
taro-build
接收--type
參數的值,接收到的結果交由dist/build.js
的build
函數進行判斷,經過判斷不一樣type
的值,決定執行對應平臺構建類型的邏輯,例如,當--type
爲h5
時,則執行dist/h5/index.js
文件中build
函數的邏輯;當--type
爲weapp
時,則執行dist/mini/index.js
文件中build
邏輯;npm
h5
的構建流程主要通過:源代碼
=> 中間代碼
=> 目標代碼
的轉換; 其中:json
src
目錄底下的代碼,若是config
中有配置sourceRoot
,則源代碼入口就爲sourceRoot
;.temp
目錄下的代碼,由taro-build
實現的中間流程,主要經過babel
實現中間代碼的轉換和生成;dist
目錄下的代碼,若是config
中配置outputRoot
,則目標代碼將輸出在outputRoot
;因此,三種代碼間的轉換關係能夠用下圖表示:redux
taro-build
幫助將源代碼轉換成中間代碼,並保存在.temp
文件夾中,中間代碼再交由webpack
進行打包構建生成目標代碼;小程序
爲何會有中間代碼生成這個步驟呢,這是由於:
源代碼
交由webpack
進行編譯,會出現部分方法的缺失、頁面沒法找到等的問題;Taro
須要根據構建平臺的類型進行一系列的轉換
,並導入對應平臺的核心包;config
對源代碼
進行轉換,並插入一些關鍵代碼
;中間代碼的生成流程須要轉換的代碼主要以src
目錄下的代碼爲主,並且只分析和轉換js和ts的文件,由於涉及到代碼的分析,因此藉助了babel
工具鏈,例如babel-core
、babel-traverse
、babel-types
和babel-template
等核心包中的方法進行處理,主要流程以下:
js或ts
,是則進行分析,不然直接複製;ENTRY文件
,PAGE文件
,NORMAL文件
,分類完成,則交由對應的處理函數進行處理;ENTRY文件
;PAGE文件
和NORMAL文件
;.temp
文件夾中;webpack-runner
,對.temp
文件的代碼進行處理,生成到dist
文件夾中;ENTRY類型
的文件,由processEntry
函數處理,經過babel-traverse
中的traverse方法對不一樣類型的AST節點進行分析,其中涉及到不少細節,主要流程以下:
config
這個ClassProperty
節點的內容,獲取pages
和subPages
;tarojs/taro
、tarojs/mobx
、tarojs/redux
相關依賴爲tarojs/taro-h5
、tarojs/mobx-h5
、tarojs/redux-h5
;轉換ImportDeclaration
節點中的alias
別名;引入Nervjs
核心包;render
函數中,加入頁面的Router
組件(根據pages
和subPages
),Provider
組件,Tabbar
組件;taro-router
相關代碼;PAGE類型
和NORMAL類型
的文件,由processOthers
函數處理,也是經過babel-traverse
中的traverse方法對不一樣類型的AST節點進行分析,這裏只列出主要流程:
tarojs/taro
、tarojs/mobx
、tarojs/redux
相關依賴爲tarojs/taro-h5
、tarojs/mobx-h5
、tarojs/redux-h5
;轉換ImportDeclaration
節點中的alias
別名;引入Nervjs
核心包;config
這個ClassProperty
節點的內容,獲取配置項,對頁面添加相關的組件和函數,例如PullDownRefresh
組件和onPageScroll
方法;nameExport
糾正爲defaultExport
,例如:當前文件page-index.js
// 糾正前 export class PageIndex extends Component { ... } // 糾正後 class PageIndex extends Component { ... } export default PageIndex;
ClassExpression
或ClassDeclaration
中,在沒有identifier
的狀況下,添加默認的identifier
爲_TaroComponentClass
:// 糾正前 export default class extends Component { ... } // 糾正後 export default class _TaroComponentClass extends Component { ... }
中間代碼生成後,緩存在.temp
文件夾底下,而且做爲webpack-runner
的入口文件,taro-build
在完成buildTemp
的流程後,就會繼續執行調用webpack-runner
的邏輯;webpack-runner
的邏輯實際上就是根據定義好的webpack
的配置,生成目標代碼的流程,後面將會有單獨的一篇文章詳述相關配置,這裏不作再多的描述;
taro-build
的小程序構建邏輯不存在中間代碼的生成,而是直接由源代碼
生成小程序能運行的目標代碼
;這裏的源代碼是指遵循React
規範的taro代碼,這種代碼在小程序的容器中是沒法直接運行的,因此須要經過taro-build轉換
成小程序可運行的代碼,所以在這個流程中涉及大量的AST語法解析和轉換
;
小程序的構建流程主要分三步完成(固然這裏還有不少細節,但本文暫不詳細闡述):
sourceDir
指定的文件,默認是app.jsx
文件,構建的邏輯由buildEntry
函數完成;app.jsx
文件中的config.pages
配置好的頁面文件,主要由buildPages
函數完成;buildSingleComponent
函數完成;構建流程須要依賴taro-transformer-wx
包去解析JSX
語法,已經對源代碼的AST語法樹
,進行代碼插入和轉換;
構建入口的邏輯大概以下:
taro-transformer-wx
中的wxTransformer
方法轉換JSX語法
;app.jsx
中的es6
語法經過babel
轉換爲es5
,而且引入taro-weapp
核心包;taro-weapp
包中createApp
函數的語句;app.json
、app.js
、app.wxss
文件;構建頁面的邏輯大概以下:
taro-transformer-wx
中的wxTransformer
方法轉換JSX語法
;es6
語法經過babel
轉換爲es5
,而且引入taro-weapp
核心包;taro-weapp
包中createComponent
函數的語句;buildDepComponents
函數實現;page.json
、page.js
、page.wxss
、page.wxml
文件;構建組件與構建頁面相似,但多了遞歸的步驟,其邏輯大概以下:
taro-transformer-wx
中的wxTransformer
方法轉換JSX語法
;es6
語法經過babel
轉換爲es5
,而且引入taro-weapp
核心包;taro-weapp
包中createComponent
函數的語句;遞歸
編譯組件所依賴的組件文件,由buildDepComponents
函數實現;page.json
、page.js
、page.wxss
、page.wxml
文件;taro
將JSX
解析到小程序模板的邏輯,單獨拆成一個包taro-transformer-wx
,裏面涉及到大量的AST解析和轉換,本文因爲篇幅的關係,暫時不詳細分析,但願後面會有單獨的文章去分析小程序AST轉換的流程
,敬請期待;
總的來講,從cli
層面去看taro的構建流程,會發現爲了兼容多平臺,taro會使用較多的AST解析和轉換
,幫助將React
規範的taro代碼轉換到對應平臺可以運行的代碼;這裏也告訴咱們,做爲一個前端er,學習和掌握AST
相關知識,能讓你看到更大的世界!
最後,本文做爲一篇原理分析的文章,若有疏漏以及錯誤,歡迎你們批評指正!