yeoman自定义脚手架使用心得

首先安装yo

1
npm install yo -g

安装mkdirp
用于创建多层目录

1
npm install --save-dev mkdirp

全局安装yeoman提供的写脚手架的脚手架 generator-generator

1
npm install generator-generator -g

创建一个目录用于存放generator

1
2
mkdir generator
cd generator

下载generator模板

1
yo generator

假设我要写一个 Generator 叫做 yzw-pc-web,根据Yeoman 的规定,你需要将这个 node 模块的名字命名为 generator-*,所以我命名为 generator-yzw-pc-web。keywords必须写成“yeoman-generator”。

回车添加一些脚手架信息

1
2
your generator name? generator-yzw-pc-web
package keywords? yeoman-generator

这个keywords一定要写

下载generator模板载成功后你可以在当前目录中找到generator-yzw-pc-web文件夹。
我们得到的generator目录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
├── generators/
│ └── app/
│ ├── index.js
│ └── templates/
│ └── dummyfile.txt
├── .editorconfig
├── .gitattributes
├── .gitignore
├── .eslintrc
├── .travis.yml
├── .yo-rc.json
├── package.json
├── gulpfile.js
├── README.md
├── LICENSE
└── test/
└── app.js

它并没有全局安装到node模块中,运行以下命令就可以在全局中使用。

npm link将本地项目放到本地全局的node_modules中,这样本地就能通过npm install generator-yzw-pc-web来安装这个包

1
2
cd generator-yzw-pc-web
npm link

往generator-yzw-pc-web里添加内容

进入generator-yzw-pc-web/generators/app/templates目录下创建package.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
"name": "<%= appname %>",
"version": "1.0.0",
"description": "<%= description %>",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"devDependencies": {
"jquery": "^3.3.1"
},
"dependencies": {
"loadash": "^1.0.0"
},
"cool": "<%= cool %>",
"author": "<%= username %>",
"license": "<%= projectLicense %>"
}

我们的generator生成什么样的基础工程,目录结构,是否自动安装依赖模块等等都是在index.js文件完成的。可以先浏览下里面内容,然后把里面的内容删掉照着下面步骤来。

打开generator-yzw-pc-web/generators/app/index.js

首先加入依赖包

1
2
const path = require('path'); // 引入Node.js中的path
const mkdirp = require('mkdirp'); // 引入mkdirp
  1. 继承generator
    1
    2
    3
    4
    5
    6
    'use strict';
    var Generator = require('yeoman-generator');

    module.exports = class extends Generator {
    //以下大部分内容将会写在里面
    };
  2. 构造函数
    1
    2
    3
    4
    5
    6
    7
    constructor(args, opts) {
    super(args, opts);
    // args是在命令行中直接传递的。 如:yo yzw-pc-web webapp,接受键值对的条件。
    this.log('args', args);
    // opts和args很相似,但是opts是作为命令行标识使用的,如yo yzw-pc-web webapp --coffee。
    this.log('opts', opts.coffee);
    }
    args是在命令行中直接传递的。 如:yo yzw-pc-web webapp,接受键值对的条件。

opts和args很相似,但是opts是作为命令行标识使用的,如yo yzw-pc-web webapp

运行

1
yo yzw-pc-web webpack --coffee

返回

1
2
args [ 'webpack' ]
opts true
  1. 初始化函数

    1
    2
    3
    4
    initializing()   {
    this.props = {}; //定义这个后面会用到
    this.log('初始化完成');
    }
  2. promoting块

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    //promts是问题集合,在调用this.promt使其在运行yo的时候提出来
    prompting() {
    // Have Yeoman greet the user.
    this.log(
    yosay(`Welcome to the terrific ${chalk.red('generator-yzw-pc-web')} generator!`)
    );

    const prompts = [
    {
    type: 'confirm',
    name: 'someAnswer',
    message: 'Would you like to enable this option?',
    default: true
    }, {
    type : 'input',
    name : 'appname',
    message : 'give Your project a name',
    default : this.appname //appname是内置对象,代表工程名,这里就是上一级的目录名
    }, {
    type : 'confirm',
    name : 'cool',
    message : 'Would you like to enable the Cool feature?'
    },
    {
    type: 'input',
    name: 'projectDesc',
    message: 'Please input project description:'
    },
    {
    type: 'list',
    name: 'projectLicense',
    message: 'Please choose license:',
    choices: ['MIT', 'ISC', 'Apache-2.0', 'AGPL-3.0']
    },
    {
    type : 'input',
    name : 'username',
    message : 'What\'s your GitHub username', //里面的单引号需要转义
    store : true
    }
    ];

    return this.prompt(prompts).then(props => {
    // To access props later use this.props.someAnswer;
    this.log('appname :', props.appname);
    this.log('cool feature :', props.cool);
    this.log('username :', props.username);
    this.log('projectDesc :', props.projectDesc);
    this.log('projectLicense :', props.projectLicense);

    //最后将用户输入的数据存在this.props中,以方便后面调用。
    this.props = props;
    });
    }
  3. default块

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    defaults () {           //判断工程名同名文件夹是否存在,不存在则自动创建
    if (path.basename(this.destinationPath()) !== this.props.appname) {
    this.log(
    'Your generator must be inside a folder named ' + this.props.appname + '\n' +
    'I\'ll automatically create this folder.'
    );
    //mkdirp是我们引用的模块,用来创建文件夹,此时没有设置项目根目录,则在当前目录创建
    mkdirp(this.props.appname);
    //this.destinationRoot则是设置要创建的工程的根目录为工程名文件夹。
    this.destinationRoot(this.destinationPath(this.props.appname));
    }
    }
  4. writing
    基于项目中generator/generator-yzw-pc-web/generators/app/templates来拷贝文件到项目工程中

generator的this.fs暴露出所有的文件方法,通过mem-fs-editor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
writing() {
//在根目录下创建文件夹
mkdirp('lib/1');

// 复制templates目录中的index.html到目标目录(先在templates里创建index.html文件)
// 会自动生成src目录
this.fs.copyTpl(
this.templatePath('src/index.html'),
this.destinationPath('src/index.html'),
{ title: 'Templating with Yeoman' }
);

this.fs.copy(
this.templatePath('dummyfile.txt'),
this.destinationPath('dummyfile.txt')
);
this.fs.copy(
this.templatePath('common'),
this.destinationPath('common')
);
this.fs.copyTpl(
this.templatePath('package.json'),
this.destinationPath('package.json'),
{
appname: this.props.appname,
cool: this.props.cool,
username: this.props.username,
description: this.props.projectDesc,
projectLicense: this.props.projectLicense
}
);
}
  1. install
    工程目录搭建的时候就会自动安装package.json里的依赖包
    1
    2
    3
    4
    5
    6
    install() {
    // 执行安装包,需要templates/package.json
    this.installDependencies();
    //使用npm安装依赖lodash
    // this.npmInstall(['lodash'], { 'save-dev': true });
    }

实际项目中使用脚手架

进入项目目录

1
cd projects

执行

1
yo yzw-web-pc

这里不包含前面的generator-

则会在projects目录下生成项目目录,你可以进入目录查看结果。

参考资料

yeoman generator自定义编写
yeoman-generator 入门教程
mem-fs-editor


yeoman自定义脚手架使用心得
https://thaneyang.github.io/2018/10/yeoman自定义脚手架使用心得.html
作者
ThaneYang
发布于
2018年10月22日
许可协议