Автоматизировать установку npm и bower с помощью grunt

У меня есть проект node/angular, который использует npm для управления зависимостями backend и bower для управления зависимостями frontend. Я хотел бы использовать задачу grunt для обеих команд установки. Я не смог понять, как это сделать.

Я попытался использовать exec, но на самом деле ничего не установил.

module.exports = function(grunt) {

    grunt.registerTask('install', 'install the backend and frontend dependencies', function() {
        // adapted from http://www.dzone.com/snippets/execute-unix-command-nodejs
        var exec = require('child_process').exec,
            sys  = require('sys');

        function puts(error, stdout, stderr) { console.log(stdout); sys.puts(stdout) }

        // assuming this command is run from the root of the repo
        exec('bower install', {cwd: './frontend'}, puts);
    });

};

Когда я cd в frontend, откройте node и запустите этот код с консоли, это отлично работает. Что я делаю неправильно в задаче ворчания?

(Я также попытался использовать API-интерфейс bower и npm, но не смог выполнить эту работу.)

Ответ 1

Вам нужно сказать, что вы используете метод async (.exec), вызывая метод this.async(), получая обратный вызов и вызывающий это, когда exec выполняется.

Это должно работать:

module.exports = function(grunt) {
    grunt.registerTask('install', 'install the backend and frontend dependencies', function() {
        var exec = require('child_process').exec;
        var cb = this.async();
        exec('bower install', {cwd: './frontend'}, function(err, stdout, stderr) {
            console.log(stdout);
            cb();
        });
    });
};

См. Почему моя асинхронная задача не завершена?

Ответ 2

Чтобы установить компоненты на стороне клиента во время npm install одновременно, чем на стороне сервера, вы можете добавить в свой package.json

"dependencies": {
    ...
    "bower" : ""
},
"scripts": {
    ...
    "postinstall" : "bower install"
}

Я предпочитаю делать разницу между установкой и тестом/сборкой

Ответ 3

FYI, вот где я сейчас.

Вы также могли бы решить проблему другим способом, то есть позволить npm обрабатывать выполнение беседки и, в конечном итоге, разрешить хруст ручку npm. См. Использовать беседу с героем.

grunt.registerTask('install', 'install the backend and frontend dependencies', function() {
    var async = require('async');
    var exec = require('child_process').exec;
    var done = this.async();

    var runCmd = function(item, callback) {
        process.stdout.write('running "' + item + '"...\n');
        var cmd = exec(item);
        cmd.stdout.on('data', function (data) {
            grunt.log.writeln(data);
        });
        cmd.stderr.on('data', function (data) {
            grunt.log.errorlns(data);
        });
        cmd.on('exit', function (code) {
            if (code !== 0) throw new Error(item + ' failed');
            grunt.log.writeln('done\n');
            callback();
        });
    };

    async.series({
        npm: function(callback){
            runCmd('npm install', callback);
        },
        bower: function(callback){
            runCmd('bower install', callback);  
        }
    },
    function(err, results) {
        if (err) done(false);
        done();
    });
});