[前端工程化]跟着taro-cli学习前端脚手架

504 阅读3分钟

最近在用taro做小程序, 还是比较喜欢cli带的create命令, 能直接创建页面, 但是功能也比较薄弱

我是使用vue3的, 但是创建的还是option样式, 便想能不能支持自定义

首先看create都接收哪些参数, 前提是你要安装@taro/cli

taro create -h

得到的结果是

$ taro create -h
👽 Taro v3.6.8

Usage: taro create [options]

Options:
  --name [name]                名称
  --description [description]  介绍
  --type [type]                模版类型(page(默认)|plugin-command|plugin-build|plugin-template)
  -h, --help                   output usage information

Synopsis:
  $ taro create page
  $ taro create --name=page --description=desc
  $ taro create my-plugin --type=plugin-command

目前看是也比较少, 然后就clone taro的工程源码来看一下

项目也是使用pnpm-workspace做的monorepo, 这个我们在前面的系列文章中有讲到这个, 不了解的可以翻回去看下

package 目录下的内容还是比较多的, 我们进入到 taro-cli 这个目录,

先看下package.json中的main字段, 是 index.js, 然后index.js中又指向了

module.exports = require('./dist/index.js').default

这里指向的是构建后的产物, 然后看了一眼package.json中的build

"build": "pnpm run clean && pnpm run prod",
"prod": "tsc",
"clean": "rimraf dist"

调用的就是先删除原来的构建产物再调用tsc命令, 这里会取读当前子项目根目录的tsconfig.json, 里面内容也比较简单, 都是默认的配置, 源码目录是 ./src, 那么我们就去src下看看, 直接看index.ts会有点晕, 只是导出了一些类和函数, 我们注意到还有个 ./bin, 每次使用 taro 都会先调用 printPkgVersion() 函数输出

console.log(`👽 Taro v${taroVersion}`)

结果就是咱们上面输出结果的第一行了, 然后是实例化一个 CLI 类, 然后调用 run()

run () {
  return this.parseArgs()
}

这个就是解析参数, 往下看, 这里用到了一个 minimist()函数来解析参数,

看仓库简单写个demo

var argv = require('minimist')(process.argv.slice(2));
console.log(argv);
node main.js create -h

得到的结果是

{ _: [ 'create' ], h: true }

如果

node main.js create -help

会得到什么呢? 是

{ _: [ 'create' ], h: true, e: true, l: true, p: true }

有点出乎意料, 这里也大概明白为什么很多cli 单横线 都会只跟单字母了 大致了解了就是解析得到了action和参数, 这时我们再回去看 package.json下是有一个

"bin": {
  "taro": "bin/taro"
},

这个是指定了这个功能是一个可执行文件, taro 等同于 node taro

接着看 parseArgs()

const _ = args._
const command = _[0]

我们的command 就是 create

剩下的代码也使用create来往下看,

判断如果是 h 则打印日志, 如果是v 则打印版本, 如果什么也不是, 那么就什么也不做,

我们的create 进入了方法 customCommand()

kernel.run({
  name: command,
  opts: {
    _: args._,
    options,
    isHelp: args.h
  }
})

直接看这里可能有点懵, 但是前面看到是kernel注册了 create.js 的, 所以剩下的执行是到 presets/commands/create.ts

const type = options.type || createTemplateTypeEnum.PAGE

这里也解释了 为什么我们不带 --type 默认给我们创建了page

创建了一个page对象, 然后调用他的create()方法

./src/create/page.ts

看到这里一个核心的内容是

export const MODIFY_CREATE_TEMPLATE = 'modifyCreateTemplate'

还有就是 args 只有这些内容

{
  pageName: name,
  projectDir: appPath,
  description,
  framework: ctx.initialConfig.framework,
  async modifyCustomTemplateConfig (cb: TSetCustomTemplateConfig) {
    await ctx.applyPlugins({ name: hooks.MODIFY_CREATE_TEMPLATE, opts: cb })
  }
}

那么 this.conf.isCustomTemplate 必然为 false

"templateInfo": {
  "name": "vue3-pinia",
  "typescript": true,
  "css": "less"
},

从package.json中读取这个配置

最终看到

getPkgTemplateInfo
"templateInfo": {
  "name": "vue3-pinia",
  "typescript": true,
  "css": "less"
},

templates目录下肯定不存在vue-pinia, 那么就看fetchTemplates() 这个函数了

是从~/.taro3.6/index.json目录下 读取templateSource 这个字段, 得到的地址是

github:NervJS/taro-project-templates#v3.6

然后看下面的 fetch, 最终发现模版在 ~/Library/pnpm/global/5/node_modules/@tarojs/cli/templates/vue3-pinia 这个目录下

然后看 template_creator.js 中的

const basePageFiles = [
  '/src/pages/index/index.css',
  '/src/pages/index/index.vue',
  '/src/pages/index/index.config.js'
]

即是我们的代码模版文件, 剩下的就是一些检查

截止到目前, 我们如果想要自定义模版的话, 就是fork一份 github:NervJS/taro-project-templates#v3.6 然后修改下里面的模版就好, 当然这个配置肯定会随着版本升级的变化而变化, 到时也跟着修改就好