这篇文章将以实例的方式来教会如何从零开始创建属于我们自己的generator。

点击获取本文示例的generator

generator创建准备

这里我们一切从零开始,在创建自己的generator之前需要做一些准备工作,比如准备好yo命令行工具,比如对生成器生成的项目结构和目录文件有清晰的规划等。

yo命令行工具

在安装了NodeJS和npm的前提下,可以通过下面的命令来安装yo命令行工具,并检查安装是否成功。

$ npm install -g yo

$ yo --version

generator-generator的安装

创建generator可以完全从零开始,也可以使用Yeoman官方提供的generator引导,这里我们选择使用Yeoman官方推荐的方式来处理。

$ mkdir YeomanTest && cd YeomanTest/ 创建新的目录并进入

$ npm install -g generator-generator 安装Yeoman引导generator

列出具体的执行情况

wendingding$ mkdir YeomanTest
wendingding$ cd YeomanTest/
wendingding$ pwd
/Users/文顶顶/Desktop/Yeoman/YeomanTest
wendingding$ npm install -g generator-generator + generator-generator@4.0.2 updated 1 package in 117.639s ╭─────────────────────────────────────╮
│ │
│ Update available 5.5.1 → 6.1.0 │
│ Run npm i -g npm to update │
│ │
╰─────────────────────────────────────╯

执行Yeoman官方的引导generator,并处理交互式配置部分,下面列出具体的执行情况。

wendingding$ yo generator
? Your generator name generator-wendingding
Your generator must be inside a folder named generator-wendingding
I'll automatically create this folder.
? Description 博客文章测试创建生成器
? Project homepage url http://www.wendingding.com
? Author's Name 文顶顶
? Author's Email 18681537032@163.com
? Author's Homepage http://www.wendingding.com
? Package keywords (comma to split) wendingding
? Send coverage reports to coveralls Yes
? GitHub username or organization flowerField
? Which license do you want to use? Apache 2.0
create package.json
create README.md
create .editorconfig
create .gitattributes
create .gitignore
create generators/app/index.js
create generators/app/templates/dummyfile.txt
create __tests__/app.js
create .travis.yml
create .eslintignore
create LICENSE
I'm all done. Running npm install for you to install the required dependencies.
If this fails, try running the command yourself.

在执行generator-generator这个生成器的过程中,会询问项目名称、作者、使用协议、主页地址等等信息,依次选择填空即可。

注意:按照约定,Yeoman generator的名字必须以“generator-”的前缀开头,这是因为所有的generator其实都是全局安装的node模块,所以Yeoman其实是完全依靠文件系统来对这些生成器进行查找操作的。

当上面的命令执行完毕后,会发现在当前的路径下面生成了generator-wendingding目录,进入到generator-wendingding目录,使用tree命令查看当前目录结构,显示如下:

.
├── LICENSE
├── README.md
├── __tests__
├── generators
├── app
│ ├── index.js
│ └── templates
│ └── dummyfile.txt
├── node_modules
├── package-lock.json
└── package.json

上面目录结构中虽然有很多文件,但我们真正需要关注的应该是generators路径下面的app/index.js文件以及templates目录,其中index文件对应是generators的组装指令部分,templates路径用于存放项目所有的模板文件。

项目模板文件准备

上面这些准备工作完成之后,接下来我们开始着手分析目标项目的文件结构,即我们使用自己创建的这个脚手架来搭建项目,其结构目录应该是怎样的?需要包含哪些文件等等。任何时候,明确知道你的目标,知道自己正在做什么至关重要。

下面试着给出目标项目的文件结构。

.
├── Gruntfile.js
├── bower.json
├── build
├── dist
├── package.json
└── src
├── css
│ └── style.css
├── index.html
├── js
│ └── index.js
├── libs
│ └── jquery
└── template

我们可以看到该项目应该包含bulidsrc以及dist三个目录,其中src目录中需要创建名为cssjslibstemplate的文件夹,分别用来保存样式文件、脚本文件、依赖的框架以及模板文件等。

除了这些必要的文件外,假设目标项目需要使用bower来进行依赖管理,使用Grunt来进行自动化构建,所以自然还应该拥有Gruntfile.js、bower.json以及package.json文件。

假设目标项目中一定会使用到jQuery框架,可能会使用到bootstrap框架。

现在我们可以开始分析生成器中应该包含项目模板文件了,也就是在generators/templates路径中应该包含哪些文件。

固定文件

index.jsstyle.css创建空文件即可。

Gruntfile.js文件因为内容固定不变,所以选择直接从旧项目中拷贝。

.jshintrc文件用于js文件语法检查,内容也是固定不变的。

.bowerrc文件用于重置Bower下载包的安装路径,内容为{"directory": "src/libs/"}

灵活文件

package.json文件中项目名称、作者以及开源协议等需要用户配置

bower.json文件的项目名称、作者、开源协议以及依赖框架等需要用户配置

可选文件

bootstrap框架相关的部分为可选文件,需要根据用户配置进行处理。

依赖文件

jQuery框架相关的部分为依赖文件,在组装指令部分通过在代码中调用方法来下载和安装。

根据上面的分析,我们在generators/templates准备了多个模板文件,下面列出文件结构以及主要文件的具体内容:

.
└── app
├── index.js
└── templates
├── Gruntfile.js
├── bower.json
├── css
│ └── style.css
├── index.html
├── js
│ └── index.js
└── package.json

package.json文件内容

{
"name": "<%= appName %>",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "<%= appAuthor %>",
"license": "<%= appLicense %>",
"devDependencies": {
"grunt": "^1.0.2",
"grunt-contrib-concat": "^1.0.1",
"grunt-contrib-cssmin": "^2.2.1",
"grunt-contrib-jshint": "^1.1.0",
"grunt-contrib-uglify": "^3.3.0",
"grunt-contrib-watch": "^1.0.0"
}
}

bower.json文件内容

{
"name": "<%= appName %>",
"description": "\"测试使用\"",
"main": "js/index.js",
"authors": [
"<%= appAuthor %>"
],
"license": "<%= appLicense %>",
"keywords": [
"generator-wendingding",
"yeoman-generator"
],
"homepage": "https://github.com/flowerField/generator-wen",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
],
"dependencies": {
"jquery": "^3.3.1"<% if(isIncludeBootstrap) { %>,
"bootstrap": "^4.1.1" <% } %>
}
}

index.html文件内容

<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title><%= appName %></title>
<link rel="stylesheet" href="css/style.css">
<script type="text/javascript" src="js/index.js"></script>
</head>
<body> </body>
</html>

Gruntfile.js文件内容

//包装函数
module.exports = function (grunt) {
// 项目配置信息
grunt.config.init({
pkg:grunt.file.readJSON("package.json"),
//代码合并
concat:{
options:{
stripBanners:true,
banner:'/*项目名称:<%=pkg.name%> 项目版本:<%=pkg.version%> 项目的作者:<%=pkg.author%> 更新时间:<%=grunt.template.today("yyyy-mm-dd")%>*/\n'
},
target:{
src:["src/js/*.js"],
dest:'build/js/index.js'
}
},
//js代码压缩
uglify:{
target:{
src:"build/js/index.js",
dest:"build/js/index.min.js"
}
},
//css代码压缩
cssmin:{
target:{
src:"src/css/style.css",
dest:"build/css/style.min.css"
}
},
//js语法检查
jshint:{
target:['Gruntfile.js',"dist/js/index.js"],
},
//监听 自动构建
watch:{
target:{
files:["src/js/*.js","src/css/*.css"],
//只要指定路径的文件(js和css)发生了变化,就自动执行tasks中列出的任务
tasks:["concat","jshint","uglify","cssmin"]
}
}
});
//通过命令行安装插件(省略...)
//从node_modules路径加载插件
grunt.loadNpmTasks("grunt-contrib-concat");
grunt.loadNpmTasks("grunt-contrib-uglify");
grunt.loadNpmTasks("grunt-contrib-cssmin");
grunt.loadNpmTasks("grunt-contrib-jshint");
grunt.loadNpmTasks("grunt-contrib-watch");
//注册任务:在执行$ grunt命令的时候依次执行代码的合并|检查|压缩等任务并开启监听
grunt.registerTask("default",["concat","jshint","uglify","cssmin","watch"]);
};
注意:上面部分文件中很多地方使用模板语法来传递参数,Yeoman所用的模板语言是EJS,具体用法请参考[EJS官网](http://www.embeddedjs.com/)

组装指令

处理完上面这些工作之后,接下来就是最最核心的部分了,我们需要在app/index.js文件中编写组装指令,这部分代码控制着这个生成器应该怎么执行,包括交互式配置的具体内容、如何复制文件以及框架依赖和Node模块下载等内容。

下面列出该示例中的index.js文件内容

'use strict';
const Generator = require('yeoman-generator');
const chalk = require('chalk');
const yosay = require('yosay');
const mkdirp = require('mkdirp'); module.exports = class extends Generator {
prompting() {
this.log(
// yosay(`Welcome to the transcendent ${chalk.red('generator-wen')} generator!`)
yosay(`欢迎使用\n${chalk.red('generator-wen')} !\n Author:文顶顶`)
); const prompts = [
{
type : 'input',
name : 'appName',
message : '请输入项目名称:',
default : this.appname //appname是内置对象,代表工程名,这里就是ys
},
{
type : 'input',
name : 'appAuthor',
message : '请输入作者姓名:',
default : '文顶顶'
},
{
type: 'list',
name: 'appLicense',
message: '请选择使用的license:',
choices: ['MIT', 'ISC', 'Apache-2.0', 'AGPL-3.0']
},
{
type : 'confirm',
name : 'isIncludeBootstrap',
message : '是否需要使用bootStrap框架?',
default : false
}, ]; return this.prompt(prompts).then(props => {
// To access props later use this.props.someAnswer;
this.props = props;
});
} writing() {
mkdirp("build");
mkdirp("dist");
mkdirp("src/template"); this.fs.copyTpl(
this.templatePath('index.html'),
this.destinationPath('src/index.html'),
{appName: this.props.appName}
); this.fs.copy(
this.templatePath('css/style.css'),
this.destinationPath('src/css/style.css')
); this.fs.copy(
this.templatePath('js/index.js'),
this.destinationPath('src/js/index.js')
); this.fs.copy(
this.templatePath('.bowerrc'),
this.destinationPath('.bowerrc')
); this.fs.copy(
this.templatePath('Gruntfile.js'),
this.destinationPath('Gruntfile.js')
); this.fs.copy(
this.templatePath('.jshintrc'),
this.destinationPath('.jshintrc')
); this.fs.copyTpl(
this.templatePath('package.json'),
this.destinationPath('package.json'),
{appName: this.props.appName,appAuthor:this.props.appAuthor,appLicense:this.props.appLicense}
); this.fs.copyTpl(
this.templatePath('bower.json'),
this.destinationPath('bower.json'),
{appName: this.props.appName,appAuthor:this.props.appAuthor,appLicense:this.props.appLicense,isIncludeBootstrap:this.props.isIncludeBootstrap}
);
} install() {
//this.installDependencies();
this.bowerInstall();
}
};

上面的代码大概由三部分组成,第一部分为prompting函数用来处理安装提示,第二部分为writing函数用来设置模板文件的复制操作,第三部分为install函数用来处理框架依赖和node包的安装。

generator的发布和测试

项目模板文件和组装指令都准备好了后,我们就可以发布自己的generator了,可以先通过$ npm link命令以软连接的方式生成一个全局的npm包,测试使用。

具体的执行细节如下

wendingding:generator-wendingding wendingding$ npm link
up to date in 3.897s
/usr/local/lib/node_modules/generator-wendingding -> /Users/文顶顶/Desktop/Yeoman/YeomanTest/generator-wendingding
wendingding:generator-wendingding wendingding$

测试·使用自己创建的generator来生成初始化项目

随便找个目录新建文件夹,使用$ yo wendingding命令即可完成项目的初始化工作。

wendingding:YeomanTest wendingding$ mkdir Demo
wendingding:YeomanTest wendingding$ cd Demo/
wendingding:Demo wendingding$ yo wendingding _-----_ ╭──────────────────────────╮
| | │ 欢迎使用 │
|--(o)--| │ generator-wen ! │
`---------´ │ Author:文顶顶 │
( _´U`_ ) ╰──────────────────────────╯
/___A___\ /
| ~ |
__'.___.'__
´ ` |° ´ Y ` ? 请输入项目名称: Demo
? 请输入作者姓名: 文顶顶
? 请选择使用的license: Apache-2.0
? 是否需要使用bootStrap框架? Yes
create bower.json
create package.json
create src/index.html
create src/css/style.css
create src/js/index.js
create .bowerrc
create Gruntfile.js
create .jshintrc
bower invalid-meta for:/Users/文顶顶/Desktop/Yeoman/YeomanTest/Demo/bower.json
bower invalid-meta The "name" is recommended to be lowercase, can contain digits, dots, dashes
bower cached https://github.com/jquery/jquery-dist.git#3.3.1
bower validate 3.3.1 against https://github.com/jquery/jquery-dist.git#^3.3.1
bower cached https://github.com/twbs/bootstrap.git#4.1.1
bower validate 4.1.1 against https://github.com/twbs/bootstrap.git#^4.1.1
bower install jquery#3.3.1
bower install bootstrap#4.1.1 jquery#3.3.1 src/libs/jquery bootstrap#4.1.1 src/libs/bootstrap
wendingding:Demo wendingding$ tree -L 3
.
├── Gruntfile.js
├── bower.json
├── build
├── dist
├── package.json
└── src
├── css
│ └── style.css
├── index.html
├── js
│ └── index.js
├── libs
│ ├── bootstrap
│ └── jquery
└── template 9 directories, 6 files

如果需要把这个生成器发布到社区,可以参考官网的说明。

前端开发系列113-工程化篇之Yeoman脚手架generator创建的更多相关文章

  1. leaflet-webpack 入门开发系列一初探篇(附源码下载)

    前言 leaflet-webpack 入门开发系列环境知识点了解: node 安装包下载webpack 打包管理工具需要依赖 node 环境,所以 node 安装包必须安装,上面链接是官网下载地址 w ...

  2. openlayers5-webpack 入门开发系列一初探篇(附源码下载)

    前言 openlayers5-webpack 入门开发系列环境知识点了解: node 安装包下载webpack 打包管理工具需要依赖 node 环境,所以 node 安装包必须安装,上面链接是官网下载 ...

  3. 【Windows10 IoT开发系列】配置篇

    原文:[Windows10 IoT开发系列]配置篇 Windows10 For IoT是Windows 10家族的一个新星,其针对不同平台拥有不同的版本.而其最重要的一个版本是运行在Raspberry ...

  4. 旨在脱离后端环境的前端开发套件 - IDT Server篇

    IDT,一个基于Nodejs的,旨在脱离后端环境的前端开发套件,目的就是能让前端开发完全脱离后端的环境,无论后端是什么模板引擎(主流),都能应付自如. IDT主要包括两大部分:Server + Bui ...

  5. 前端开发【第2篇:CSS】

    鸡血 样式的属性多达几千个,但别担心,按照80-20原则,常用的也就几十个,你完全可以掌握它. Css初识 HTML的诞生 早期只有HTML的时候为了让HTML更美观一点,当时页面的开发者会把颜色写到 ...

  6. [置顶]【实用 .NET Core开发系列】- 导航篇

    前言 此系列从出发点来看,是 上个系列的续篇, 上个系列因为后面工作的原因,后面几篇没有写完,后来.NET Core出来之后,注意力就转移到了.NET Core上,所以再也就没有继续下去,此是原因之一 ...

  7. openlayers4 入门开发系列之风场图篇

    前言 openlayers4 官网的 api 文档介绍地址 openlayers4 api,里面详细的介绍 openlayers4 各个类的介绍,还有就是在线例子:openlayers4 官网在线例子 ...

  8. openlayers4 入门开发系列之热力图篇(附源码下载)

    前言 openlayers4 官网的 api 文档介绍地址 openlayers4 api,里面详细的介绍 openlayers4 各个类的介绍,还有就是在线例子:openlayers4 官网在线例子 ...

  9. Android Metro风格的Launcher开发系列第三篇

    前言: 各位小伙伴,又到了每周更新文章了时候了,本来是周日能发出来呢,这不是赶上清明节吗,女王大人发话了,清明节前两天半陪她玩,只留给我周一下午半天时间写博客,哪里有女王哪里就有压迫呀有木有!好了闲话 ...

  10. cesium-webpack 入门开发系列一初探篇(附源码下载)

    前言 cesium-webpack 入门开发系列环境知识点了解: node 安装包下载webpack 打包管理工具需要依赖 node 环境,所以 node 安装包必须安装,上面链接是官网下载地址 we ...

随机推荐

  1. iOS Facebook和Google登录

    前言 最近在对接完Google和Facebook登录之后准备对这部分内容做一个小小的总结,方便以后有需要的时候查看. 具体的Google账号申请和Facebook账号的申请在这里就不做介绍了,这部分内 ...

  2. 🎀java-自定义日志注解

    简介 创建自定义日志注解,对相关接口记录请求日志. 环境 SpringBoot 实现 注解定义 定义注解类 package com.zk.app.annotation; import com.zk.a ...

  3. B站插入外站链接地址(现已禁用)

    问题描述: B站中插入链接时,无法插入外站链接,提示[请输入正确的站内链接地址]: 日常文章编写中,经常需要插入外站链接跳转,以便于用户快速定位 分析: B站专栏文章编辑使用的富文本编辑器,应该是支持 ...

  4. 如何使用 MySQL 的 EXPLAIN 语句进行查询分析?

    如何使用 MySQL 的 EXPLAIN 语句进行查询分析? EXPLAIN 是 MySQL 提供的分析 SQL 查询执行计划的工具,用于了解查询语句的执行过程,帮助优化查询性能. 1. EXPLAI ...

  5. 【BUG】未能加载文件或程序集“System.Runtime.CompilerServices.Unsafe, Version=4.0.4.1, Culture=neutral, PublicKeyT

    参考:无法加载文件或程序集System.Runtime.CompilerServices.Unsafe. 问题 我的环境: Visual Studio 2019 出错代码: MSBuildWorksp ...

  6. k8s-v1.22.5部署文档(ubuntu1804)

    1,# 临时关闭sudo swapoff -a# 永久关闭sudo vi /etc/fstab## 第二行注释掉 (注释swap分区)# /dev/mapper/ubuntu--vg-swap_1 n ...

  7. 小程序简单 tab 切换实现

    也是终于找到了数据可视化的最佳载体, 用小程序来做可视化简直完美. 尤其对于像我这种搞数据的, 数据分析, 数据报表, 可视化一直是一个巨大难题, 当我认识的最终的方案还是要用前端的时候, 感觉还有麻 ...

  8. AI对低代码技术的影响

    一.开发效率革命的"双引擎" 在过去的数十年里,软件工程领域正在经历一场由低代码平台和人工智能技术共同驱动的效率革命.这两股技术浪潮虽源于不同的技术路径,却共同指向同一个战略目标: ...

  9. Predixy的docker化

    概述 当前已有一套redis cluster的集群,但是fs中的hiredis只能配置单实例redis. AI了一下方案,可以使用redis的proxy组件来实现从hiredis到redis clus ...

  10. IIS设置发布公告页面

    IIS原有站点停用 IIS新增里新增一个站点,端口及域名和原有站点一致 新增公告提示页面,如:index.html 新增web.config文件,并设置web.config 1 <system. ...