Automate npm and bower install with grunt

Javascriptnode.jsNpmBowerGruntjs

Javascript Problem Overview


I have a node / angular project that uses npm for backend dependency management and bower for frontend dependency management. I'd like to use a grunt task to do both install commands. I haven't been able to figure out how to do it.

I made an attempt using exec, but it doesn't actually install anything.

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

};

When I cd into frontend, open up node, and run this code from the console, this works fine. What am I doing wrong in the grunt task?

(I also tried to use the bower and npm APIs, but couldn't make that work either.)

Javascript Solutions


Solution 1 - Javascript

To install client side components during npm install at the same time than server side libs, you can add in your package.json

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

I prefer to make the difference between install and test/build

Solution 2 - Javascript

You need to tell grunt that you're using an async method (.exec) by calling the this.async() method, getting a callback, and calling that when exec is done.

This should work:

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

See Why doesn't my asynchronous task complete?

Solution 3 - Javascript

FYI, here is where i am for now.

You could also have taken the problem another way, i.e. let npm handle the execution of bower, and ultimately let grunt handle npm. See Use bower with heroku.

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

Solution 4 - Javascript

Grunt task that does just this job (as per Sindre's solution above):

https://github.com/ahutchings/grunt-install-dependencies

Solution 5 - Javascript

Grunt task that does the bower install command : https://github.com/yatskevich/grunt-bower-task

also , you can use https://github.com/stephenplusplus/grunt-bower-install

to auto inject your dependencies into the index.html file

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNick HeinerView Question on Stackoverflow
Solution 1 - JavascriptjsanView Answer on Stackoverflow
Solution 2 - JavascriptSindre SorhusView Answer on Stackoverflow
Solution 3 - Javascriptxavier.seignardView Answer on Stackoverflow
Solution 4 - JavascriptnostopbuttonView Answer on Stackoverflow
Solution 5 - JavascriptItsik AvidanView Answer on Stackoverflow