脚手架工具:前端工程化的发起者
脚手架的本质作用:
软件开发领域,脚手架是指通过各种工具来生成项目基础代码的技术。创建项目基础结构、提供项目规范和约定。
- 相同的组织结构
- 相同的开发范式
- 相同的模块依赖
- 相同的工具配置
- 相同的基础代码
- 例子:IDE创建项目的过程就是一个脚手架的工作流程
常用脚手架工具:
- React.js项目 -> create-react-app
- Vue.js项目 -> vue-cli
- Angular 项目 -> angular-cli
- Yeoman:可以通过yeoman自定义自己需要的脚手架工具
- Plop: 根据具体的模板生产相应的代码文件
Yeoman的使用
Yeoman是一款通用的脚手架系统,允许创建任何类型的应用程序,与语言无关。
Yeoman脚手架的使用
# 在全局范围安装yo
$ npm install yo --global # or yarn global add yo
# 安装对应的generator
$ npm install generator-node --global # or yarn global add generator-node
# 通过yo运行generator
$ cd path/to/project-dir
$ mkdir my-module
$ yo node
sub-generator: 除了创建工程的脚手架,Yeoman还提供了sub-generator
用于创建模块或组件,例如yo angular:controller MyNewController
可以为项目添加新的controller
常规使用步骤
- 明确你的需求
- 找到合适的Generator
- 全局范围安装找到的Generator
- 通过Yo运行对应的Generator
- 通过命令行交互填写选项
- 生成你所需要的项目结构
自定义Generator
- Generator本质上(核心)就是一个NPM模块
- 项目名称必须以
generator-name
的格式进行命名,generator-
前缀必须有,后面name是生成器的名称 - 在
package.json
中,除了项目名称必须为gererator-name
的形式,keywords
字段里面也必须包含yeoman-generator
关键词。{
"name": "generator-name",
"version": "0.1.0",
"description": "",
"files": [
"generators"
],
"keywords": ["yeoman-generator"],
"dependencies": {
"yeoman-generator": "^1.0.0"
}
}
generator的基本项目结构
创建generator流程&示例
- 创建项目目录
mkdir generator-sample
&cd generator-sample
- 初始化项目
yarn init
ornpm init
- 安装
yeoman-generator
yarn add yeoman-generator
ornpm install yeoman-generator
- 创建默认生成器目录
mkdir -p generators/app
&touch generators/app/index.js
,该文件将作为默认生成器的入口文件 - Yeoman提供了一个基础的Generator类,我们可以继承它实现自己的一些行为,每次调用生成器,被添加到类prototype中的方法也都会被当做任务,执行一次,通常是按顺序执行,某些特殊的方法可能会触发特定的顺序 ```javascript //generators/app/index.js const Generator = require(‘yeoman-generator’);
module.exports = class extends Generator { // 重写构造函数,构造函数中可能会运行一些特殊的方法,例如设置重要的状态控件,而它们无法再构造函数外部执行 constructor(args, opts) { super(args, opts); } sayHello() { // 在使用脚手架生成项目时会先打印hello world,prototype中的普通方法会依次按顺序执行 console.log(‘hello world’) } // 简单的写入文件操作 writing() { this.fs.write( this.destinationPath(‘temp.txt’), Math.random().toString() ) } }
6. 创建Npm包链接`yarn link` or `npm link`
7. 使用`yo sample`即可创建项目,生成temp.txt文件。
<a name="52d6cc30"></a>
#### 不会被当做任务的方法
- **私有方法不会被当做任务:** 上面提到能被`Object.getPrototypeOf(Generator)`获取到的方法都是generator的任务,其中有个特例为私有方法`以_开头的方法`不会被当做任务
```javascript
// yeoman官方给出的示例代码
class extends Generator {
// 会被当做任务自动执行
method1() {
console.log('hey 1');
}
// 不会被当做任务自动执行
_private_method() {
console.log('private hey');
}
}
实例方法不会被当做任务执行:
// yeoman官方给出的示例代码
class extends Generator {
constructor(args, opts) {
// Calling the super constructor is important so our generator is correctly set up
super(args, opts)
// 实例方法不会被当做任务执行
this.helperMethod = function () {
console.log('won\'t be called automatically');
};
}
}
继承自父Generator的方法不会被当做任务:
// yeoman官方给出的示例代码
class MyBase extends Generator {
helper() {
console.log('methods on the parent generator won\'t be called automatically');
}
}
module.exports = class extends MyBase {
// exec不会被当做任务自动执行
exec() {
this.helper();
}
};
plop的使用
一个小而美的脚手架工具
- 将plop模块作为项目开发依赖安装
- 在项目根目录下创建一个plopfile.js文件
- 在plofile.fs文件中定义脚手架任务
- 编写用于生成特定类型文件的模板
- 通过plop提供的CLI运行脚手架任务
node cli应用
脚手架本身就是一个node的cli应用,我们可以通过node cli应用来实现自己的脚手架。通过以上对Yeoman与Plop.js的介绍,我们可以发现它们在实现时都使用了 inquirer.js 与用户进行交互。使用node cli应用实现脚手架,我们可以选择inquirer.js结合结合commander.js,并搭配各种小工具例如chalk.js, log-symbols等小工具自定义一些输出信息。node cli应用的核心就是在
package.json
中添加一个"bin"
字段,指向js cli脚本,js脚本的书写方式必须由以下代码开头,其他代码则为正常的js代码
#!/usr/bin/env node
console.log('hello')
通过node实现脚手架的方案
- 创建一个项目
xxx-cli
,yarn init
初始化项目 添加
bin/cli.js
文件,并填写如下代码#!/usr/bin/env node
console.log('hello world')
在
package.json
中添加bin
字段{
"name": "node-cli",
"version": "1.0.0",
"main": "index.js",
"bin": {
"node-cli": "./bin/cli.js"
},
"license": "MIT",
"dependencies": {
"ejs": "^3.1.5",
"inquirer": "^7.3.3"
}
}
在项目根目录通过
npm link
或者yarn link
创建全局软连接- 如果在mac或linux下编写代码还需要给cli脚本添加执行权限
chmod 755 ./bin/cli.js
- 然后随便进入一个目录,执行
node-cli
,注意你自己在bin字段下填写的key是什么,命令就是什么,这里是node-cli
,然后输出hello world
至此使用node实现了cli的应用,脚手架所需的基本知识已经具备。
除此之外,脚手架本质上就是通过cli与用户进行各种交互,收集回答后根据用户回答选择性地创建项目模板。所以再结合 inquirer.js 或commander.js 可以进行与用户的交互,并收集回答。
结合 ejs template syntax 等模板方案,根据收集的回答,为用户生成相应的基础代码。