Include Gruntfile and run a task in an another file - node.js

I have an app using Grunt, that I launch in my terminal, and I want to run a task through an another app.
So I'd like to know how can I include my Gruntfile.js to this other app, and run the task.
For now this new app is really basic, juste a simple local web page using NodeJS, with a button that launch the task.
Gruntfile (I want to run the "archive" task)
module.exports = function (grunt) {
require('time-grunt')(grunt);
require('jit-grunt')(grunt, {
ngtemplates: "grunt-angular-templates"
});
var Generator = require("./generator.js")(grunt);
var generator = new Generator();
generator.printLogo();
// Build
grunt.registerTask("build", function (fileType) {
//definition of build task
grunt.task.run(tasks);
});
// Archive Task.
grunt.registerTask("archive", ["build", "compress", "clean:post-rsync"]);
};
Other file : (I tried a require, It seems to work, but I can't run the "archive" task of the Gruntfile.)
var grunt = require('grunt');
var gruntfile = require('./Gruntfile.js')(grunt);
var app = express();
app.get('/', function(req, res){
res.render('test.ejs');
});
app.post('/create', function(req, res){
//run grunt task "archive" here
//gruntfile.grunt.registerTask("archive", ["build"]);
res.redirect('/');
});
app.listen(8080);
Do you have any idea how could I run the task in my gruntfile in this other file ?
(The function printLogo() is working so i'm sure the Gruntfile is include)
Thank you very much (I'm a beginner with Grunt so sorry if I miss something trivial)

You can just run a command from node. This way you don’t have to worry about dependencies and what not. You just spawn grunt, like you normally would, except programatically.
var spawn = require('child_process').spawn;
// This will run the 'archive' task of grunt
spawn('grunt', ['archive'], {
cwd: 'path/to/grunt/project'
});

Grunt is a command line tool, the cleanest approach here would be to refactor your Gruntfile and extract your task's logics into a library.
Then from your Gruntfile's task you can call that library, and from your /create route you can also call your library.

You can use grunt-hub plugin:
grunt.initConfig({
hub: {
all: {
src: ['../*/Gruntfile.js'],
tasks: ['jshint', 'nodeunit'],
},
},
});

Related

Trouble getting Grunt to run node.js script

I am a grunt and node noob but I managed to write a node script that does what I want it to and works from the command line. I don't want to publish the script as a node module but I would like to run it from my grunt file.
What changes (if any) do I need to make to the script for this to work?
The more I read about configuring grunt files and custom tasks the more confused I get. I currently have something that looks like this:
module.exports = function(grunt) {
grunt.initConfig({
'mytaskname': 'what goes here?'
});
grunt.loadNpmTasks('./node_modules/script_name');
grunt.registerTask('run-from-command-line', 'description', function() {
grunt.log.writeln('Not running...');
});
}
Any help would be greatly appreciated.
You could use the grunt-execute plugin for doing this which executes files in a node.js child process.
Example:
If your node script is in "node-scripts/script.js", Gruntfile.js would look something like this:
module.exports = function(grunt) {
grunt.initConfig({
execute: {
target: {
src: ["node-scripts/script.js"]
}
}
});
// Load the plugins
grunt.loadNpmTasks("grunt-execute");
grunt.registerTask("default", ["execute"]);
};

Inconsistent Results with Running Gulp from Visual Studio on Post Build

I'm running gulp 3.9.0 and calling some gulp commands from Visual Studio 2013. The flow is such that whenever I build in VS, gulp should clean my temporary and output files, then after a successful build, compile my javascript assets into one file.
The problem is that, I've noticed that after running "gulp build", sometimes my assets are not generated at all. This even happens on the command line. After running "gulp clean" (which removes the output), I have to run "gulp build" twice just to see the output materialize. It's as if gulp is failing silently. Not sure if this is an issue with Node running on Windows or if I have misconfigured something.
Note that VS is responsible for compiling all TypeScript files into a single .js in the \output folder.
Apologies in advanced if there is a better way to do what I'm trying to do. Still a gulp/node newbie.
VS Pre-Build:
gulp clean
VS Post-Build:
gulp build
gulpfile.js:
var gulp = require('gulp');
var del = require('del');
var concat = require('gulp-concat');
var ngAnnotate = require('gulp-ng-annotate');
var uglify = require('gulp-uglify');
var templateCache = require('gulp-angular-templatecache');
var concatCss = require('gulp-concat-css');
var minifyCss = require('gulp-minify-css');
gulp.task("cleanOutdatedLibraries", function(){
del("./Libs/*");
del(['./myapp.js', './myapp.min.js', './myapp.css'])
});
gulp.task("cleanTemporaryFiles", function(){
del("./output/*");
});
/** Run gulp clean on prebuild */
gulp.task('clean', ["cleanOutdatedLibraries", "cleanTemporaryFiles"])
gulp.task('copyNewestLibraries', function(){
var bowerFiles = ['angular/angular.min.js',
'angular/angular.js',
'angular/angular.min.js.map',
'angular-ui-router/release/angular-ui-router.min.js',
'angular-local-storage/dist/angular-local-storage.min.js',
'jquery/dist/jquery.min.js',
'jquery/dist/jquery.min.map',
'lodash/lodash.min.js',
'angular-resource/angular-resource.min.js',
'angular-resource/angular-resource.min.js.map',
'momentjs/min/moment.min.js',
'angular-loading-bar/src/loading-bar.js',
'ngDialog/js/ngDialog.min.js'];
gulp.src(bowerFiles, {cwd: "./bower_components/"})
.pipe(gulp.dest('./Libs'));
});
gulp.task('copyThirdPartyLibraries', function(){
var thirdPartyFiles = ['jquery-ui.min.js',
'angular-sanitize.min.js'];
gulp.src(thirdPartyFiles, {cwd: "./_thirdparty/"})
.pipe(gulp.dest('./Libs'));
});
/** Merge all Angular JS HTML templates into a cache */
gulp.task('mergeHtmlTemplatesIntoAngularCache', function(){
gulp.src('app/**/*.html')
.pipe(templateCache("templates.js", {
module: "myapp"
}))
.pipe(gulp.dest('./output/'));
});
gulp.task('produceMinfiedApp', function(){
gulp.src(['app/**/*.js', 'output/typescripts.js'])
.pipe(concat('bundle.min.js'))
.pipe(ngAnnotate())
.pipe(uglify())
.pipe(gulp.dest('./output/'));
gulp.src(['output/bundle.min.js', 'output/templates.js'])
.pipe(concat('myapp.min.js'))
.pipe(gulp.dest('./'));
});
gulp.task('produceApp', function(){
gulp.src(['app/**/*.js', 'output/typescripts.js'])
.pipe(concat('bundle.js'))
.pipe(ngAnnotate())
.pipe(gulp.dest('./output/'));
gulp.src(['output/bundle.js', 'output/templates.js'])
.pipe(concat('myapp.js'))
.pipe(gulp.dest('./'));
});
gulp.task('mergeStyles', function(){
gulp.src(['Styles/**/*.css'])
.pipe(concat('styles.css'))
.pipe(gulp.dest("./output/"));
gulp.src(['app/**/*.css'])
.pipe(concat('app.css'))
.pipe(gulp.dest("./output/"));
gulp.src(['output/styles.css', 'output/app.css'])
.pipe(concatCss("./myapp.css"))
.pipe(minifyCss({compatibility: 'ie10'}))
.pipe(gulp.dest('./'));
});
/** Run gulp build on post build */
gulp.task('build', ["copyNewestLibraries",
"copyThirdPartyLibraries",
"mergeHtmlTemplatesIntoAngularCache",
"produceMinfiedApp",
"produceApp",
"mergeStyles"]);
/** Run gulp build on post build */
gulp.task('build', ["copyNewestLibraries",
"copyThirdPartyLibraries",
"mergeHtmlTemplatesIntoAngularCache",
"produceMinfiedApp",
"produceApp",
"mergeStyles"]);
These tasks (copyNewestLibraries, produceApp, etc.) run asynchronously, in no particular order. E.g. produceApp may finish before copyNewestLibraries, which is probably not what you want.
See How to run Gulp tasks sequentially one after the other for more info.

How to package node webkit app

I'm developing my first node webkit app. I'm confused about packing the files. Is the end product a single file that can be executed ?
The end result will not be a single executable, you must also include some DLLs in your zip-file.
These line in github made me more confused.
How is the packaging done ?
Do I need to include the webkit files also in the package or just the files I have created ?
I packaged my node-webkit app successfully for various platforms by using the below gulp script. Below is the script which is self explanatory.
Reference : https://github.com/nwjs/nwbuilder/blob/master/example/Gulpfile.js
var NwBuilder = require('nw-builder');
var gulp = require('gulp');
var gutil = require('gulp-util');
gulp.task('nw', function () {
var nw = new NwBuilder({
version: '0.12.3',
files: '../nodepoc/**',
platforms: ['osx64','win32','win64']
});
// Log stuff you want
nw.on('log', function (msg) {
gutil.log('nw-builder', msg);
});
// Build returns a promise, return it so the task isn't called in parallel
return nw.build().catch(function (err) {
gutil.log('nw-builder', err);
});
});
gulp.task('default', ['nw']);
Save the file as gulpFile.js. In terminal , simply run gulp command in the same location as that of the gulpFile.js and it will download the necessary node-webkit distributions for the platforms and build the package for you.

Gulp, livereload, jade

Need help.
I use gulp-conect and it livereload method. But if I build a few template in time, get a lot of page refresh. Is any solution, I want to build few templates with single page refresh?
So, I reproduce the problem you have and came accross this working solution.
First, lets check gulp plugins you need:
gulp-jade
gulp-livereload
optional: gulp-load-plugins
In case you need some of them go to:
http://gulpjs.com/plugins/
Search for them and install them.
Strategy: I created a gulp task called live that will check your *.jade files, and as you are working on a certain file & saving it, gulp will compile it into html and refresh the browser.
In order to accomplish that, we define a function called compileAndRefresh that will take the file returned by the watcher. It will compile that file into html and the refesh the browser (test with livereload plugin for chrome).
Notes:
I always use gulp-load-plugin to load plugins, so thats whay I use plugins.jad and plugins.livereload.
This will only compile files that are saved and while you have the task live exucting on the command line. Will not compile other files that are not in use. In order to accomplish that, you need to define a task that compiles all files, not only the ones that have been changed.
Assume .jade files in /jade and html output to /html
So, here is the gulpfile.js:
var gulp = require('gulp'),
gulpLoadPlugins = require('gulp-load-plugins'),
plugins = gulpLoadPlugins();
gulp.task('webserver', function() {
gulp.src('./html')
.pipe(plugins.webserver({
livereload: true
}));
gulp.watch('./jade/*.jade', function(event) {
compileAndRefresh(event.path);
});
});
function compileAndRefresh(file) {
gulp.src(file)
.pipe(plugins.jade({
}))
.pipe(gulp.dest('./html'))
}
Post edit notes:
Removed liveReload call from compileAndRefresh (webserver will do that).
Use gulp-server plugin insted of gulp-connect, as they suggest on their repository: "New plugin based on connect 3 using the gulp.src() API. Written in plain javascript. https://github.com/schickling/gulp-webserver"
Something you can do is to watch only files that changes, and then apply a function only to those files that have been changed, something like this:
gulp.task('live', function() {
gulp.watch('templates/folder', function(event) {
refresh_templates(event.path);
});
});
function refresh_templates(file) {
return
gulp.src(file)
.pipe(plugins.embedlr())
.pipe(plugins.livereload());
}
PS: this is not a working example, and I dont know if you are using embedlr, but the point, is that you can watch, and use a callback to call another function with the files that are changing, and the manipulate only those files. Also, I supposed that your goal is to refresh the templates for your browser, but you manipulate as you like, save them on dest or do whatever you want.
Key point here is to show how to manipulate file that changes: callback of watch + custom function.
var jadeTask = function(path) {
path = path || loc.jade + '/*.jade';
if (/source/.test(path)) {
path = loc.jade + '/**/*.jade';
}
return gulp.src(path)
.pipe(changed(loc.markup, {extension: '.html'}))
.pipe(jade({
locals : json_array,
pretty : true
}))
.pipe(gulp.dest(loc.markup))
.pipe(connect.reload());
}
First install required plugins
gulp
express
gulp-jade
connect-livereload
tiny-lr
connect
then write the code
var gulp = require('gulp');
var express = require('express');
var path = require('path');
var connect = require("connect");
var jade = require('gulp-jade');
var app = express();
gulp.task('express', function() {
app.use(require('connect-livereload')({port: 8002}));
app.use(express.static(path.join(__dirname, '/dist')));
app.listen(8000);
});
var tinylr;
gulp.task('livereload', function() {
tinylr = require('tiny-lr')();
tinylr.listen(8002);
});
function notifyLiveReload(event) {
var fileName = require('path').relative(__dirname, event.path);
tinylr.changed({
body: {
files: [fileName]
}
});
}
gulp.task('jade', function(){
gulp.src('src/*.jade')
.pipe(jade())
.pipe(gulp.dest('dist'))
});
gulp.task('watch', function() {
gulp.watch('dist/*.html', notifyLiveReload);
gulp.watch('src/*.jade', ['jade']);
});
gulp.task('default', ['livereload', 'express', 'watch', 'jade'], function() {
});
find the example here at GitHub

Using grunt to run a node server and do cleanup after

So basically this is what I want to do. Have a grunt script that compiles my coffee files to JS. Then run the node server and then, either after the server closes or while it's still running, delete the JS files that were the result of the compilation and only keep the .coffee ones.
I'm having a couple of issues getting it to work. Most importantly, the way I'm currently doing it is this:
grunt.loadNpmTasks("grunt-contrib-coffee");
grunt.registerTask("node", "Starting node server", function () {
var done = this.async();
console.log("test");
var sp = grunt.util.spawn({
cmd: "node",
args: ["index"]
}, function (err, res, code) {
console.log(err, res, code);
done();
});
});
grunt.registerTask("default", ["coffee", "node"]);
The problem here is that the node serer isn't run in the same process as grunt. This matters because I can't just CTRL-C once to terminate JUST the node server.
Ideally, I'd like to have it run in the same process and have the grunt script pause while it's waiting for me to CTRL-C the server. Then, after it's finished, I want grunt to remove the said files.
How can I achieve this?
Edit: Note that the snippet doesn't have the actual removal implemented since I can't get this to work.
If you keep the variable sp in a more global scope, you can define a task node:kill that simply checks whether sp === null (or similar), and if not, does sp.kill(). Then you can simply run the node:kill task after your testing task. You could additionally invoke a separate task that just deletes the generated JS files.
For something similar I used grunt-shell-spawn in conjunction with a shutdown listener.
In your grunt initConfig:
shell: {
runSuperCoolJavaServer:{
command:'java -jar mysupercoolserver.jar',
options: {
async:true //spawn it instead!
}
}
},
Then outside of initConfig, you can set up a listener for when the user ctrl+c's out of your grunt task:
grunt.registerTask("superCoolServerShutdownListener",function(step){
var name = this.name;
if (step === 'exit') process.exit();
else {
process.on("SIGINT",function(){
grunt.log.writeln("").writeln("Shutting down super cool server...");
grunt.task.run(["shell:runSuperCoolJavaServer:kill"]); //the key!
grunt.task.current.async()();
});
}
});
Finally, register the tasks
grunt.registerTask('serverWithKill', [
'runSuperCoolJavaServer',
'superCoolServerShutdownListener']
);

Resources