我的Yeoman生成器完成安装后如何运行Grunt任务?

Sov*_*iut 24 javascript gruntjs yeoman yeoman-generator

我正在构建一个定制的Yeoman生成器,它安装了许多预处理的语言编译器,如CoffeeScript,LESS和Jade.在我的生成器创建的Gruntfile中,我有一个构建任务,可以编译所有内容.但是,在该构建任务至少运行一次之前,编译的HTML,CSS和Javascript文件不存在,如果我尝试在新建脚手架之后运行grunt watch/connect服务器,这可能会造成混淆.

在安装结束时让我的生成器运行Grunt构建步骤的最佳方法是什么?end已经习惯用来打电话的事件this.installDependencies似乎是正确的地方,但我应该如何与Grunt沟通?

Ste*_*hen 48

如果你跟着堆栈,this.installDependencies最终会一直向下到https://github.com/yeoman/generator/blob/45258c0a48edfb917ecf915e842b091a26d17f3e/lib/actions/install.js#L36:

this.spawnCommand(installer, args, cb)
  .on('error', cb)
  .on('exit', this.emit.bind(this, installer + 'Install:end', paths))
  .on('exit', function (err) {
    if (err === 127) {
      this.log.error('Could not find ' + installer + '. Please install with ' +
                          '`npm install -g ' + installer + '`.');
    }
    cb(err);
  }.bind(this));
Run Code Online (Sandbox Code Playgroud)

进一步追逐这个,this.spawnCommand来自https://github.com/yeoman/generator/blob/master/lib/actions/spawn_command.js:

var spawn = require('child_process').spawn;
var win32 = process.platform === 'win32';

/**
 * Normalize a command across OS and spawn it.
 *
 * @param {String} command
 * @param {Array} args
 */

module.exports = function spawnCommand(command, args) {
  var winCommand = win32 ? 'cmd' : command;
  var winArgs = win32 ? ['/c'].concat(command, args) : args;

  return spawn(winCommand, winArgs, { stdio: 'inherit' });
};
Run Code Online (Sandbox Code Playgroud)

换句话说,在您的Generator代码中,您可以this.spawnCommand随时调用,并将您希望终端运行的参数传递给它.如,this.spawnCommand('grunt', ['build']).

那么接下来的问题是你把它放在哪里?线性思考,您只能相信grunt build在安装所有依赖项之后才能工作.

https://github.com/yeoman/generator/blob/45258c0a48edfb917ecf915e842b091a26d17f3e/lib/actions/install.js#L67-69, this.installDependencies接受回调,因此您的代码可能如下所示:

this.on('end', function () {
  this.installDependencies({
    skipInstall: this.options['skip-install'],
    callback: function () {
      this.spawnCommand('grunt', ['build']);
    }.bind(this) // bind the callback to the parent scope
  });
});
Run Code Online (Sandbox Code Playgroud)

试一试!如果一切顺利,您应该在新this.spawnCommand呼叫之上添加一些错误处理以确保安全.


Ash*_*Ash 16

我已经使用了Stephen的好答案,通过以下方式实现自定义事件以保持整洁.

MyGenerator = module.exports = function MyGenerator(args, options, config) {

    this.on('end', function () {
        this.installDependencies({
            skipInstall: options['skip-install'],
            callback: function() {
                // Emit a new event - dependencies installed
                this.emit('dependenciesInstalled');
            }.bind(this)
        });
    });

    // Now you can bind to the dependencies installed event
    this.on('dependenciesInstalled', function() {
        this.spawnCommand('grunt', ['build']);
    });

};
Run Code Online (Sandbox Code Playgroud)