Might be ignorance - but
dfitzhenry opened this issue · comments
Is there a ( probably obvious, I'm node-new ) way to have the express server reload when your server.js or similar file changes? I know nodemon is typically for this, but it seems within the watch context there might be a way in grunt-express-server?
I've been doing it with several projects, including this one:
https://github.com/ericclemmons/genesis-skeleton/blob/master/Gruntfile.coffee#L177-L180
It's pretty much watching the server files & re-running the express task.
When in doubt, post up your gruntfile!
Thank you much for the reply, it was ignorance on my part ( didn't have the server files(s) ) configured in the express/server config. However, I'm not sure if it's my watch config or what, but when express:dev tries to restart, I get the error : EADDRINUSE meaning the instance wasn't killed I take it. Probably something wrong with my setup, here is my gruntfile, and again, really appreciate it - I'm sort of a hands on learner, so hacking my way through grunt...
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
root: './',
src: './src/web',
target: './target/user-ux.war',
// uglify: {
// options: {
// banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'
// }
// // },
// // build: {
// // src: '<%= src %>/js/test.js',
// // dest: '<%= target %>/js/test.min.js'
// // }
// },
less: {
prod: {
options: {
paths: ["<%= target %>/css"]
},
files: {
"<%= target %>/css/template.css": "<%= src %>/css/template.less"
},
cleanCss: "true"
}
},
jshint: {
// define the files to lint
files: ['<%= target %>/js/{,*/}*.js', '<%=root%>/test/**/*.js'],
// configure JSHint (documented at http://www.jshint.com/docs/)
options: {
// more options here if you want to override JSHint defaults
globals: {
jQuery: true,
console: true,
module: true
},
ignores: ['<%=target %>/js/lib.js' ]
}
},
copy: {
user_ux: {
files: [
{
expand: true,
cwd: '<%= src %>/js',
src: ['**/*.js'],
dest: '<%= target %>/js'
},
{
expand: true,
cwd: '<%= src %>/css',
src: ['**/*.less'],
dest: '<%= target %>/css'
},
{
expand: true,
cwd: '<%= src %>/',
src: ['*.html'],
dest: '<%= target %>/'
},
]
},
everything: {
files: [
{
expand: true,
cwd: "<%= src %>",
src: [
"**"
],
dest: '<%= target %>'
}
]
}
},
clean: {
// build: ["path/to/dir/one", "path/to/dir/two"],
user_ux: ["<%= target %>"]
},
// Performs rewrites based on filerev and the useminPrepare configuration
usemin: {
html: ['<%= target %>/{,*/}*.html'],
css: ['<%= target %>/css/{,*/}*.css'],
// js: ['<%= target %>/js/{,*/}*.js'],
options: {
assetsDirs: ['<%= target %>','<%= target %>/image']
}
},
useminPrepare: {
html: '<%= src %>/index.html',
options: {
root: '<%= target %>',
dest: '<%= target %>',
flow: {
html: {
steps: {
js: ['concat'],
css: ['cssmin']
},
post: {}
}
}
}
},
express: {
options: {},
dev: {
options: {
script: './server.js'
},
livereload: {
options: {
server: './server.js',
livereload: true,
serverreload: true,
bases: ['./<%=target%>']
}
}
}
},
connect: {
options: {
port: 35729,
livereload: true,
serverreload: true,
open: true,
hostname: '0.0.0.0',
directory: "./target/user-ux.war",
base: "./target/user-ux.war",
},
dev: {
options: {
middleware: function (connect) {
return [
require('connect-livereload')() // <--- here
];
}
}
}
},
closureCompiler: {
options: {
// most options here omitted for brevity
compilerFile: 'node_modules/closure-compiler/lib/vendor/compiler.jar',
compilerOpts: {
// most options here omitted for brevity
compilation_level: 'ADVANCED_OPTIMIZATIONS',
create_source_map: true,
warning_level: "verbose",
summary_detail_level: 3
}
},
minify: {
files: [
{
expand: true,
src: ['<%= target %>/js/application.js']
// ext: '.min.js'
}
]
}
},
ngmin: {
controllers: {
src: ['<%=src%>/js/controllers/**/*.js'],
dest: '<%=target%>/js/controllers'
},
directives: {
expand: true,
// cwd: 'test/src',
src: ['<%=src%>/js/directives/**/*.js'],
dest: '<%=target%>/js/directives'
}
}
});
// ** Dependencies **
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-connect');
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-less');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks("grunt-bower-install-simple"); // Updates bower libraries prior to build or server tasks
grunt.loadNpmTasks('grunt-closure-tools');
grunt.loadNpmTasks('grunt-express-server');
grunt.loadNpmTasks('grunt-newer');
grunt.loadNpmTasks('grunt-ngmin');
grunt.loadNpmTasks('grunt-usemin');
// ** Express dev config for both watch configs **
var expressDevWatchConfig = {
files: [ "<%=root%>/server.js" ],
tasks: [ 'express:dev' ],
options: {
spawn: true // for grunt-contrib-watch v0.5.0+, "nospawn: true" for lower versions. Without this option specified express won't be reloaded
}
};
// ** Less dev config for both watch configs **
var lessDevWatchConfig = {
files: ['<%= target %>/css/*.less'],
tasks: ['less'],
options: {
livereload: true
}
};
// ** Watch Task for Quick Dev Mode **
grunt.registerTask('watch:quickdev', function() {
// Configuration for watch:test tasks.
var config = {
staticWatch: {
files: ['<%= src %>/css/**/*.less',
'<%= src %>/js/**/*.js',
'<%= src %>/*.html'],
tasks: ['copy-newer'],
options: {
livereload: true
}
},
lessWatch: lessDevWatchConfig,
express: expressDevWatchConfig
};
grunt.config('watch', config);
grunt.task.run('watch');
});
// ** Watch Task for Full Dev Mode **
grunt.registerTask('watch:fulldev', function() {
// Configuration for watch:test tasks.
var config = {
staticWatch: {
files: ['<%= src %>/css/**/*.less',
'<%= src %>/js/**/*.js',
'<%= src %>/*.html'],
tasks: ['copy-newer', 'runBuild'],
options: {
livereload: true
}
},
lessWatch: lessDevWatchConfig,
express: expressDevWatchConfig
};
grunt.config('watch', config);
grunt.task.run('watch');
});
// ** Tasks **
grunt.registerTask('copy-newer', ['newer:copy:user_ux']);
grunt.registerTask('prepareBuild', [
'bower-install-simple',
'clean',
'copy:everything'
]);
grunt.registerTask('runBuild', [
'less',
// 'ngmin',
'useminPrepare',
'concat',
'jshint',
'cssmin',
'usemin',
'closureCompiler'
]);
grunt.registerTask('build', ['prepareBuild', 'runBuild']);
grunt.registerTask('default', ['prepareBuild', 'less', 'express:dev', 'watch:quickdev' ]);
grunt.registerTask('fulldev', ['build', 'less', 'express:dev', 'watch:fulldev' ]);
};
Nevermind I got it, not sure what the implications are, but I changed spawn to false on the express watch config, and it worked. Thanks again for the help though...
I think the "problem" is, that grunt-express-server spawns the server in a child task, but watch also offers this functionality, but when both are turned on, watch spawns a child of grunt-express-server which also spawns a child and somehow the grandchild isn't killed properly on a kill of the child.
Maybe because the child is killed before the grandchild ;)
sounds macabre..
actually we could and should change this..
grunt-contrib-watch is killing with SIGINT
So this:
process.on('SIGINT', this.finished)
process.on('SIGINT', this.stop)
additional to this
could do the trick, I will test it
nope, no way getting this to work.
With
spawn: true
atBegin: true
my grunt-express-server tasks doesn't even live long enough to start the server ;)
I think the grunt.util.spawn isn't designed for nesting..
Not sure if it's relevant, but grunt-watch specifically is not meant for nesting per their site, but I'm not sure if that's relevant to multiple configs, or how it spawns processes ( or both ). Do you think there is any harm in changing spawn to false, which worked for me to fix this, even though my grunt watch is v0.6.1? Maybe I read it wrong, but they want spawn to be true for > 0.5.0 I believe...
There is no harm ;) they just defined it as default.. but it is simply not compatible with grunt-express-server.
Thats probably the reason why spawn:false
is mentioned in the readme.
Sweet, thanks to ya'll for handholding :)