使用yeoman创建属于你自己的脚手架
现代前端开发,由于构建工具的大规模使用,项目的配置趋于日渐复杂。很多时候你只是需要快速编写一个简单的demo,但是你首先需要做的可能是花费不少的时间搭建一整套的前端工具链。为了解决这个问题,社区创造出了不少比较成熟的脚手架或者boilerplate来让开发者快速搭建项目。但是如果你想快速的定制化属于你自己的脚手架,今天要聊的yeoman可能是一个不错的选择。
什么是yeoman generator
真正开始写一个yeoman脚手架之前,我们需要先搞清楚 generator
这个名词。
generator是yeoman提供的对于脚手架的封装,每一个generator是一个单独的npm package。不同的generator之间可以通过组合生成新的generator(e.g. generator-generator是对于generator-node的组合)
如果你想使用一个已经发布的generator,你只需要
|
|
如何编写一个yeoman generator
上面也提到过generator其实是yeoman提供的一个对于脚手架抽象的封装,所以在yeoman对于generator的项目结构也做出了一些开发者必须要满足的要求。
在项目的package.json中
- 项目必须依赖于 yeoman-generator,
- 项目 keywords 必须有 yemoan-generator
- package名应该以generator-[generator-name]的格式进行命名
项目结构
yeoman generator支持两种不同的项目组织模式
模式1
├───package.json
└───generators/
├───app/
│ └───index.js
└───router/
└───index.js
模式2
├───package.json
├───app/
│ └───index.js
└───router/
└───index.js
需要注意的是, 第二种模式下必须要在pacakge.json里面显式的做出声明
|
|
一个最简单的generator
以下是一个最简单的Generator
|
|
运行 npm link
将你本地的generator link到全局的path中, 然后运行 yo foo
。
console将会打印出 method1 just ran
和 method2 just ran
。
私有方法
yeoman在运行时会把所有的class内部的class方法都进行调用,如果你只是想做一些逻辑的规整和抽离,并不想抽离出来的这些方法被调用,你可以使用yeoman提供的两种私有方法声明方式。
|
|
or
|
|
yeoman还提供了通过extends generator的方法去创建私有方法,Extend a parent generator 但是笔者认为这个方式不够优雅,不太推荐大家使用。
Run Loop
yeoman内部通过Grouped-queue 实现了一套定义好的任务队列,任务队列的顺序如下。
- initializing - 初始化脚手架,读取yeoman配置等。
- prompting - 通过this.prompt()与用户进行交互。
- configuring - 编辑和配置项目的配置文件。
- default - 如果generator内部还有不符合任意一个任务队列任务名的方法,将会被放在default这个任务下进行运行。
- writing - 将预置好的模板进行填充
- conflicts - 处理冲突,比如文件名重复等(仅限内部使用)
- install - 进行依赖的安装(如npm, bower)
- end - 最后一个任务,一般在这个任务里面会进行一些clean up之类的工作
每一个任务通过实现一个对应名字的class method来进行声明
|
|
Prompt
yeoman使用了 Inquirer 来做用户提示
Inquirer 支持以下几种类型的用户提示
- input
- confirm
- list
- rawlist
- expand
- checkbox
- password
- editor
yeoman通过prompt任务中调用this.prompt来进行用户提示。
|
|
需要注意的是,所有的console输出yeoman都推荐使用内建的 this.log()
而不是 console.log()
或者 =process.stdout.write()=进行输出。
Argument 和 options
作为一个CLI工具,如何得到用户输入的argument和options也是一个很需要考虑的问题。好消息是yeoman也帮我们做了封装。
Argument?
怎样得到 my-project?
yo webapp my-project
|
|
argument 有以下options可以在定义一个argument的时候传入。
- desc argument描述
- required 是否必须
- type String,Number,Array或者function
- default 这个argument的default value
options
怎样得到 –foo?
yo webapp --foo
|
|
option 有以下几个options可以在定义一个optins的时候传入。
- desc option描述
- alias option的short name, 比如
-h
可以定义为--help
的short name - type Boolean,String, Number或者function
- default 这个option的default value
- hide 这个option是否要在–help中隐藏
需要注意的是,不管是option还是argument,都需要把定义声明在constructor中
文件命令
Yeoman 封装了一系列路径和文件操作的语法糖来很便利的提供使用者与文件系统的交互。
this.destinationRoot() 是一个对于destination位置的语法糖,支持传入文件或者目录名进行连接。
|
|
对于generator中包含的模板的地址,yeoman也提供了一些语法糖来帮助我们取得其路径。
|
|
修改一个模板
yeoman提供了一个fs.copyTpl方法来进行模板的填充。fs.copyTpl方法默认使用ejs模板。
|
|
|
|
渲染后的结果
|
|
参考资料
- 本文链接: https://hateonion.me/posts/18dec17/
- 版权声明: 本站所有文章均采用 CC BY-NC-SA 4.0 协议进行许可。如需转载,请注明出处。