yeoman_通过4个简单的步骤创建自定义Yeoman Generator

yeoman

Yeoman is one of the web's most popular tooling frameworks with over 400 contributed reusable plugins. The open source project led by Addy Osmani makes project scaffolding an easy step.

Yeoman是Web上最受欢迎的工具框架之一,拥有400多个可重用的可重用插件。 由Addy Osmani领导的开源项目使项目脚手架轻松完成。

This means that basic project structures and dependencies can now be setup with just one or two commands from the CLI. Is that not amazing? You don't have to install Express, Passport, Angular, Mongoose, etc that your MEAN project require manually, you just need to create and configure once, and then use throughout your other projects.

这意味着现在可以仅使用CLI中的一两个命令来设置基本项目结构和依赖项。 难道不令人惊奇吗? 您无需手动安装MEAN项目所需的ExpressPassportAngularMongoose等,只需创建和配置一次,然后在其他所有项目中使用。

yeoman-logo

Note that Yeoman is not just for JavaScript based projects but for anything you can make out of it.

请注意,Yeoman不仅适用于基于JavaScript的项目,还适用于您可以利用它进行的所有操作。

Yeoman's plugins are called generators and are made in such a way that they suite a particular project requirements or workflow. It is not a surprise that out of the 400 contributed generators, you might not find one that suits you.

Yeoman的插件称为generators ,其制作方式使其适合特定的项目需求或工作流程。 不足为奇的是,在400个贡献生成器中,您可能找不到适合您的一个。

Today, I will guide you through 4 easy steps to create yours and also provide a demo at the end. We will end up with a MEAN generator for Scotch.

今天,我将指导您完成4个简单的步骤来创建您的步骤,并在最后提供一个演示。 我们将最终获得苏格兰威士忌的MEAN生成器。

步骤1:安装和设置 ( STEP 1: Installation and Setup )

As always, the first step is to install the dependencies and create a new generator project. The concept is actually using a yeoman generator to generate a generator template. That sounds silly right?

与往常一样,第一步是安装依赖项并创建一个新的生成器项目。 该概念实际上是使用yeoman生成器生成生成器模板。 听起来很傻吧?

The Yeoman team built a generator plugin that makes building a Yeoman custom generator quite easy. So install both Yeoman (yo) and the generator (generator-generator is the name):

Yeoman团队构建了一个生成器插件,这使得构建Yeoman定制生成器变得非常容易。 因此,请同时安装Yeoman( yo )和发电机( generator-generator是名称):

npm install -g yo generator-generator

This command installs both Yeoman and the generator plugin. Installing these tools does not create a project, they just download them to your file system. To setup a generator project, run:

此命令将同时安装Yeoman和generator插件。 安装这些工具不会创建项目,它们只是将它们下载到您的文件系统中。 要设置生成器项目,请运行:

yo generator

You will be asked two or more questions from the CLI including your GitHub username and your generator base name. Yeoman generators naming convention is in such a way that the generators are prefixed with generator- and the name of the custom generator (base name) added right after the -.

CLI会向您询问两个或多个问题,包括您的GitHub用户名和生成器基本名称。 Yeoman生成器的命名约定是这样的:生成器以generator-器-为前缀,并且自定义生成器的名称(基本名称)紧跟在-

In our case, I chose, scotchmean so that at the end, the generator will be used as generator-scotchmean.

在本例中,我选择了scotchmean以便最后将generator用作generator-scotchmean

You do not have to be intimidated by the file structure. Actually we just need one folder which is the generators folder. The generators folder has an app directory with templates and index.js. The templates are files that will be generated when we use this generators to scaffold a project and the index.js folder holds all the logics involved in generating a template.

您不必被文件结构吓到。 实际上,我们只需要一个文件夹,即generators文件夹。 generators文件夹有一个包含templatesindex.jsapp目录。 templates是当我们使用此生成器来构建项目时将生成的文件,而index.js文件夹包含生成模板所涉及的所有逻辑。

Before we move to step 2, clear the contents of app/templates/index.js and replace with:

在进行步骤2之前,请清除app/templates/index.js的内容并替换为:

'use strict';
//Require dependencies
var yeoman = require('yeoman-generator');
var chalk = require('chalk');
var yosay = require('yosay');


module.exports = yeoman.generators.Base.extend({
//Configurations will be loaded here.
});

步骤2:要求输入 ( STEP 2: Asking For Input )

One awesome feature of Yeoman is it's ability to scaffold a project using the user's decision from inputs. This means that we can configure a lot of options like the project's name, dependencies we need, and much more. Yeoman uses Inquire.js to accomplish this feature. To keep it minimal, we just need to get the project's name from input:

Yeoman的一项令人敬畏的功能是能够根据用户输入的决定来为项目提供支架。 这意味着我们可以配置很多选项,例如项目的名称,所需的依赖项等等。 Yeoman使用Inquire.js完成此功能。 为了使它最小化,我们只需要从输入中获取项目的名称:

//Configurations will be loaded here.
//Ask for user input
prompting: function() {
  var done = this.async();
  this.prompt({
    type: 'input',
    name: 'name',
    message: 'Your project name',
    //Defaults to the project's folder name if the input is skipped
    default: this.appname
  }, function(answers) {
    this.props = answers
    this.log(answers.name);
    done();
  }.bind(this));
},
//Writing Logic here

We are using the async() method to make sure that the function does not exit before the actual work gets completed.

我们正在使用async()方法来确保该函数在实际工作完成之前不会退出。

The prompt method is used to get the user's input which is of type input as there are other types.

prompt方法用于获取用户输入,该input是其他类型的 input

The name property of the prompt is used to access the field's value from the project and the message is the instruction. We also want it to default to the folder name if we do not provide a name while scaffolding.

提示的name属性用于从项目中访问该字段的值,并且message为指令。 如果我们在脚手架上不提供名称,我们也希望它默认为文件夹名称。

The second argument of prompt is a callback which holds the values from the prompt(s). We have set this.props up with the answers so it can be accessed from the "writing" logic.

prompt的第二个参数是一个回调,其中包含提示中的值。 我们已经为this.props设置了答案,以便可以从“编写”逻辑中访问它。

步骤3:使用模板脚手架 ( STEP 3: Scaffolding With Templates )

Template files are files generated when you use Yeoman with your custom generator to generate a project. These files are located within the templates folder in the app directory. It works like common view engines like EJS. You can dynamically fill in data into the templates with the inputs that were generated. We will use a basic MEAN folder structure for our templates:

模板文件是将Yeoman与自定义生成器一起使用以生成项目时生成的文件。 这些文件位于app目录中的templates文件夹中。 它像EJS这样的通用视图引擎一样工作。 您可以使用生成的输入将数据动态填写到模板中。 我们将为模板使用基本的MEAN文件夹结构:

|---public
    |-----css
        |-----app.css           
    |-----js
        |-----app.js
|---routes
    |-----all.js
|---model
    |-----todo.js
|---views
    |-----index.ejs
|---server.js
|---bower.json
|---package.json
|---etc

Just like a normal application, replace the above project structure with the contents of the templates folder and then we will gradually populate them in a stepwise manner or create them along the process. All template logic are wrapped inside the writing object in index.js:

就像普通的应用程序一样,将上面的项目结构替换为templates文件夹的内容,然后我们将逐步地逐步填充它们,或者在此过程中创建它们。 所有模板逻辑都包装在index.js中的writing对象内:

//Writing Logic here
writing: {
  //Copy the configuration files

  //Copy application files

  //Install Dependencies
},

The files to be generated are better classified into configuration files and application files. The config files include package.json, bower.json, and other utility files for our project while the app files include server.js, our routes, public directory and every other major files.

要生成的文件可以更好地分为配置文件和应用程序文件。 配置文件包括package.jsonbower.json和用于我们项目的其他实用程序文件,而应用程序文件包括server.js ,我们的路由,公共目录以及所有其他主要文件。

We will first create the configuration files templates and then copy them. To create the files, open app/templates/_package.json and replace with:

我们将首先创建配置文件模板,然后将其复制。 要创建文件,请打开app/templates/_package.json并替换为:

{
    "name": "<%= name %>",    
    "scripts": {
        "start": "node server.js"
    },
    "dependencies": {
        "express": "^4.13.3",
        "ejs": "^2.3.4",
        "body-parser": "^1.14.0",
        "cookie-parser": "~1.0.1",
        "mongoose":"^4.2.4"
    }     
}

Also replace app/templates/_bower.json with:

app/templates/_bower.json为:

{
    "name": "<%= name %>",
    "version": "0.0.0",
    "dependencies": {
        "bootstrap": "3.3.5",
        "angular": "1.4.6"
    }
}

Now create a bowerrc in app/templates/ and fill it with:

现在在app/templates/创建一个bowerrc并填充:

{
    "directory" : "app/public/libs"
}

Update app/index.js:

更新app/index.js

//Writing Logic here
writing: {
  //Copy the configuration files
  config: function () {
          this.fs.copyTpl(
              this.templatePath('_package.json'),
              this.destinationPath('package.json'), {
                  name: this.props.name
              }
          );
          this.fs.copyTpl(
              this.templatePath('_bower.json'),
              this.destinationPath('bower.json'), {
                  name: this.props.name
              }
          );
          this.fs.copy(
            this.templatePath('bowerrc'),
            this.destinationPath('.bowerrc')
          );
      },

  //Copy application files

  //Install Dependencies
},

Two methods, copy() and copyTpl() are used to the copy the templates from our template path to a destination path which Yeoman abstracts from us the implementation but helps determine the path we intend to copy the files to.

copy()copyTpl()这两种方法用于将模板从我们的模板路径复制到目标路径,Yeoman从我们的实现中抽象出该路径,但有助于确定我们要将文件复制到的路径。

The difference between the two methods is that copyTpl() takes a third parameter which is a list of data to be bound to the template file after it is generated while copy() is used when there are no bindings required in the template.

两种方法之间的区别在于, copyTpl()采用第三个参数,该参数是在生成模板文件后要绑定到模板文件的数据的列表,而当模板中不需要绑定时使用copy()

Now we have the setup files prepared and we can now go ahead and create the application files. I suggest we begin with the server.js as it is our entry point:

现在我们已经准备好安装文件,现在可以继续创建应用程序文件了。 我建议我们从server.js开始,因为它是我们的切入点:

//Dependencies
var express = require('express');
var app = express();
var path = require('path');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var mongoose = require('mongoose');

//Create a mongoose connection
mongoose.connect('mongodb://127.0.0.1:27017/scotchmean');
//Load custom dependencies
var routes = require('./routes/all');


//View engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

//Configure Body Pareser and Cookie Parser
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.use(cookieParser());

//Use the public folder for static files
app.use(express.static(path.join(__dirname, 'public')));

console.log(routes.getTodo)
//Create the routes
app.get('/', routes.index);
app.get('/todo', routes.getTodo);
app.post('/todo', routes.postTodo);

//Set port to env.Port or default to 8080
app.set('port', process.env.PORT || 8080);
//Listen to port for connections
app.listen(app.get('port'), function() {
  console.log('App listening at port ' + app.get('port'));
});

The above snippet is a basic server file for Node. We just ended up loading routes (though yet to be implemented), configuring body and cookie parser, creating a connection to MongoDB and listening to a port.

上面的代码片段是Node的基本服务器文件。 我们刚刚结束了加载路由(尽管尚未实现),配置正文和cookie解析器,创建与MongoDB的连接以及侦听端口。

Next up is to create the routes which include: index, getTodo and postTodo. Create a _routes folder inside the templates directory. Add _all.js with the following content:

接下来是创建路由,包括: indexgetTodopostTodo 。 在templates目录中创建一个_routes文件夹。 添加具有以下内容的_all.js

//_routes/_all.js
var Todo = require('../model/todo').todo;
exports.index = function(req, res){
  res.render('index');
};


exports.getTodo = function(req, res){
  Todo.find().exec(function(err, todo){
    if (err)
      return res.send(err);
    return res.json(todo);
  });
};

exports.postTodo = function(req, res){
  Todo.create(req.body, function(err, todo){
    if (err)
      return res.send(err);
    return res.json(todo);
  });
};

We can now create the Todo model that the route loaded. Create a _model folder in templates directory and add a file named _todo.js in it with the following content:

现在,我们可以创建路线加载的Todo模型。 在templates目录中创建一个_model文件夹,并在其中添加一个名为_todo.js的文件,其内容如下:

//_model/_todo.js
var mongoose = require('mongoose');
var todo = mongoose.model('Todo', {
              content: String
          });

exports.todo = todo;

Time to develop our views and public files. We need just one EJS view which is index for our home page as seen in the routes. This file will live in the _views folder in the templates directory:

是时候发展我们的观点和公共文件了。 我们只需要一个EJS视图,该视图就是我们的主页的index ,如在路线中所示。 该文件将位于templates目录的_views文件夹中:

<html ng-app="app">

  <body ng-controller="TodoController">
    <div class="container">
      <div class="col-md-4 col-md-offset-4">
        <input type="text" ng-model="todo.content" class="form-control">
        <button type="button" ng-click="addTodo()" class="btn btn-primary">Add</button>
        <hr>
        <ul>
          <li ng-repeat="todo in todos">{{todo.content}}</li>
        </ul>
      </div>
    </div>
    <script src="libs/angular/angular.js"></script>
    <script src="js/app.js"></script>
  </body>
</html>

See how we are binding the name value to the view in the title. That is the most interesting part of this file. The rest is just basic HTML with Bootstrap and Angular codes.

了解我们如何将name值绑定到title的视图。 那是该文件最有趣的部分。 其余的只是带有Bootstrap和Angular代码的基本HTML。

Moving further, create the _public folder with _css and _js directories. In the _js folder add a file _app.js to hold our Angular logic:

进一步,使用_css_js目录创建_public文件夹。 在_js文件夹中添加文件_app.js来保存我们的Angular逻辑:

angular.module('app', [])
  .controller('TodoController', function($scope, $http) {
    $scope.todos = [];
    $scope.todo = {};
    $http.get('/todo').success(function(data) {
      $scope.todos = data;
    });
    $scope.addTodo = function() {
      $http.post('/todo', $scope.todo).success(function(data) {
        $scope.todos.unshift(data);
      });
      $scope.todo = {};
    };
  });

Now create a file in the _css directory named _app.css with this content:

现在,在_css目录中创建一个名为_app.css的文件,其内容如下:

body{
  padding-top:50px;
}

We have created all the template files that our project need but yet to update the index.js to be able to scaffold and serve them at project scaffold. Let us do so:

我们已经创建了项目需要的所有模板文件,但尚未更新index.js以便能够进行脚手架并在项目脚手架上提供它们。 让我们这样做:

//Copy application files
app: function() {
  //Server file
  this.fs.copyTpl(
    this.templatePath('_server.js'),
    this.destinationPath('server.js'),
    this.destinationPath('/views/index.ejs'), {
      name: this.props.name
    }
  );
  /Routes
  this.fs.copy(
    this.templatePath('_routes/_all.js'),
    this.destinationPath('routes/all.js'));


  // Model
  this.fs.copy(
    this.templatePath('_model/_todo.js'),
    this.destinationPath('model/todo.js'));

  // Views
  this.fs.copyTpl(
    this.templatePath('_views/_index.ejs'),
    this.destinationPath('/views/index.ejs'), {
      name: this.props.name
    }
  );

  // Public/
  this.fs.copy(
    this.templatePath('_public/_css/_app.css'),
    this.destinationPath('public/css/app.css')
  );
  this.fs.copy(
    this.templatePath('_public/_js/_app.js'),
    this.destinationPath('public/js/app.js')
  );
}
},
//Install Dependencies

Finally on step 3 is to install all the dependencies once the scaffold is completed by updating index.js to:

最后,在第3步是在完成脚手架后通过将index.js更新为以下内容来安装所有依赖项:

//Install Dependencies
install: function() {
  this.installDependencies();
}

步骤4:测试 ( STEP 4: Testing )

The most reasonable way to carry out integration test is not to publish to npm registry and then install before we can run yo scotchmean to create a project.

进行集成测试的最合理方法是,不发布到npm注册表,然后安装,然后运行yo scotchmean创建项目。

We can utilize npm's link to assist us with linking the generator in the global node modules. To understand better, on the generator's project folder, run:

我们可以利用npm的link来帮助我们在全局节点模块中链接生成器。 为了更好地理解,请在生成器的项目文件夹中运行:

npm link

Navigate to a folder you would love to scaffold a new MEAN project and run:

导航到您希望构建新的MEAN项目并运行的文件夹:

yo scotchmean

Respond to the prompts and watch Yo do its magic. Do have in mind that you do not need to keep running npm link command to update changes before testing. Just edit and save then your project will be ready for another scaffold.

响应提示并观看Yo发挥其魔力。 请记住,您无需继续运行npm link命令即可在测试之前更新更改。 只需编辑并保存,您的项目就可以准备使用另一个脚手架了。

When you are satisfied with what you have built, you can publish to npm.

当您对自己的构建感到满意时,可以将其发布到npm。

结论 ( Conclusion )

Hopefully, you can start making your life easier with Yeoman and it's generators. It doesn't end with a basic example; try something crazy, publish on npm, share on GitHub and earn some credits. Feel free to leave a comment below and Scotch will always give you all the attention yo deserve.

希望您可以开始使用Yeoman及其发电机来简化生活。 它不以一个基本的例子结尾。 尝试一些疯狂的事情,在npm上发布,在GitHub上共享并获得一些积分。 随时在下面发表评论,苏格兰威士忌将始终为您提供应有的关注。

Demo

演示版

翻译自: https://scotch.io/tutorials/create-a-custom-yeoman-generator-in-4-easy-steps

yeoman

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值