使用Grunt自动化npm和bower安装

63

我有一个使用npm管理后端依赖和bower管理前端依赖的node/angular项目。我想使用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进入前端目录,打开node并在控制台中运行此代码时,它可以正常工作。我在grunt任务中做错了什么?
(我还尝试过使用bower和npm API,但也无法使其工作。)

我处于相同的配置中,想知道你是如何运行npm install的?是以相同的方式吗?还是有其他方法? - xavier.seignard
5个回答

134

如果你希望在npm install时同时安装客户端组件和服务器端库,可以在package.json中添加如下内容:

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

我更倾向于区分安装和测试/构建的差异


10
最简化的解决方案,明确地分离构建和开发设置问题,而不需要添加额外的 Grunt 任务别名或需要向我的项目添加额外文档。这太棒了,谢谢! - Conrad.Dean
3
非常好的......非常干净利落 - mynameistechno
2
如此简单!非常非常简单。这绝对是最优雅的解决方案。谢谢。 - mtpultz
2
"postinstall": "bower install" 在这种情况下也可以正常工作,因为 node_modules/.bin 已经被添加到 PATH 环境变量中。 - Farid Nouri Neshat
1
npm 运行脚本时会自动添加它,因此它可以在任何地方运行。 - Farid Nouri Neshat
显示剩余4条评论

35

你需要通过调用this.async()方法来告诉grunt你正在使用异步方法(.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();
        });
    });
};

请查看为什么我的异步任务没有完成?


7

我目前的位置是:FYI。

你也可以采用另一种方法来解决问题,即让npm处理bower的执行,并最终由grunt处理npm。请参见在Heroku中使用Bower

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();
    });
});

2

2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接