众所周知,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
相关知识,能让你看到更大的世界!
最后,本文做为一篇原理分析的文章,若有疏漏以及错误,欢迎你们批评指正!