Dive in Taro (深入解读Taro)
前言
闲赋在家,读读代码,顺便写写文章,本文首发简书,源码看到哪就更新到哪。
项目概览
lerna
taro 用 lerna 做多模块管理,lerna 多见于中大型项目,比如 babel。
taro 想要在开发环境下跑起来,只需要:
cd taro目录
npm i
npm run bootstrap => npm-run-all clear-all bootstrap:lerna
npm run bootstrap
做了两个事情:
-
clear-all
清理所有的旧依赖
rimraf package-lock.json packages/*/node_modules packages/*/package-lock.json
-
bootstrap:lerna
初始化 lerna
lerna bootstrap -- --ignore-engines
(--ignore-engines 这个参数是给 npm client 的)
其中第二步 bootstrap:lerna
具体做了:
-
npm install
all external dependencies of each package. - Symlink together all Lerna
packages
that are dependencies of each other.
这一步尤其重要,因为多模块开发最烦人的问题就是开发的时候模块间可能会互相依赖,如果本地的模块符合指定版本的话,lerna 会自动帮你软链上,不然就会去 npm 下载。值得留意的是, 如果有A依赖了一个小于当前版本的B,也就是说本地这个B版本更高,lerna会自动帮你去下载旧的那个版本B,所以版本问题你也不用操心了。 -
npm run prepublish
in all bootstrapped packages. -
npm run prepare
in all bootstrapped packages.
参考
- lerna bootstrap
taro-cli
脚手架工具,用于初始化 taro 项目,编译成多端平台代码
bin/taro
先从入口文件 bin/taro
说起,项目用了 tj/commander
,这可以说是 tj 大神在 js 叱咤风云时的一大杰作,灵感来源于 ruby 的 commander。
taro 使用了像 git 一样的子命令,taro init xxx
,在 commander 你只需要在 bin/
目录下,创建对应的 program-command
文件即可,比如 taro-init
,taro-build
等。
bin/taro-init
taro-init 文件就是传递命令行的参数进去,无需介绍太多,重点在于我是怎么一步一步看代码的。
node 现在 debug 已经很方便,方法如下:
node --inspect-brk ~/wip/to-be-read/taro/packages/taro-cli/bin/taro-init myApp # 找到入口文件,像教程一样开始新手教学
chrome://inspect # 打开 chrome,输入,找到 remote target 点击进去即可
简单理一下 init 的过程:
- Project.new
- .ask (
return inquirer.prompt(prompts)
) 询问用户各种配置 - .ask 返回的配置赋值给 project.conf
- .ask (
- Project.write
-
const templateCreate = require(path.join(this.templatePath(), template, 'index.js'))
动态加载对应的 template 的index.js
文件 - 然后传参 (project.conf) 进去初始化,生成对应的模板文件
-
bin/taro-build
不同的端对应的逻辑在:
- h5.js
- weapp.js - swan
- weapp.js - alipay
- weapp.js - weapp
- rn.js
- ui.js (专门给 taro-ui 用的)
weapp build 大致过程
-
buildProjectConfig()
复制 taro 根目录下的project.config.json
到dist/
,并把miniprogramRoot
改成./
, 这样就可以把dist/
拖到微信开发者工具,而不是整个taro 项目,解决了频繁编译问题
-
copyFiles()
小程序编译增加 copy 功能,用于把taro项目的资源拷贝到对应的端
参考:
- https://github.com/coolzilj/taro/commit/0132a0ecda029b3bac2b3cf605e6e67193fec37d
- 配置详情 · Taro
- buildEntry()
编译入口文件(src/app.js
)
具体步骤如下:
- fs 读取入口文件的代码,等到字符串
entryFileCode
- @tarojs/transformer-wx 转换
entryFileCode
得到transformResult
(把 Nerv 组件转换为小程序代码) -
parseAst(transformResult.ast)
解析入口文件 ast 得到 res - compileScriptFile(res.code) 得到 resCode,就是编译好的 app.js
- buildPages()
Babel
一般来说,将一种结构化语言的代码编译成另一种类似的结构化语言的代码包括以下几个步骤:
image.png
参考:
- https://github.com/jamiebuilds/babel-handbook/blob/master/translations/en/plugin-handbook.md
- http://www.alloyteam.com/2017/04/analysis-of-babel-babel-overview/
- https://www.h5jun.com/post/babel-for-es6-and-beyond.html
- https://astexplorer.net/