Подтвердить что ты не робот

Как запустить задачу Grunt после того, как генератор Yeoman завершит установку?

Я создаю пользовательский генератор Yeoman, который устанавливает много предварительно обработанных компиляторов языка, таких как CoffeeScript, LESS и Jade. В Gruntfile, который создает мой генератор, у меня есть задача сборки, которая компилирует все. Однако до тех пор, пока эта задача сборки не будет запущена хотя бы один раз, скомпилированные файлы HTML, CSS и Javascript не существуют, что может сбить с толку, если я попытаюсь запустить сервер grunt watch/connect после новых лесов.

Каков наилучший способ заставить мой генератор запустить этот шаг сборки Grunt в конце установки? Событие end, которое уже используется для вызова this.installDependencies, кажется правильным местом для этого, но как мне связаться с Grunt?

4b9b3361

Ответ 1

Если вы следуете за стеком, 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));

Продолжая это дальше, 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' });
};

Другими словами, в коде 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
  });
});

Сделайте снимок! Если все идет хорошо, вы должны добавить некоторую обработку ошибок поверх этого нового вызова this.spawnCommand, чтобы быть в безопасности.

Ответ 2

Я использовал отличный ответ Стивена, реализованный следующим образом с помощью специального события, чтобы поддерживать порядок вещей.

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']);
    });

};

Ответ 3

Этот вопрос уже немного старый, но я все же хочу сделать это дополнение, если кто-то его пропустил. Процессы после установки теперь проще реализовать. Посмотрите на цикл цикла и используйте метод end, где вы можете запускать все вещи после установки.