How to bind server and client at grunt.js? - node.js

I'm new at mean stack develop.
I have a project in which it is necessary to add a user interface which compile through grunt.
My server starting at command node server and gruntfile compile all my client side. But I need my grunt start server and compile all views.
I added grunt-express, added it to tasks but when I make grunt serve there is no server side on it. It stayed on port 3000.
How can I implement two sides on grunt compile?
Gruntfile.js
"use strict";
var LIVERELOAD_PORT, lrSnippet, mountFolder;
LIVERELOAD_PORT = 35728;
lrSnippet = require("connect-livereload")({
port: LIVERELOAD_PORT
});
mountFolder = function(connect, dir) {
return connect["static"](require("path").resolve(dir));
};
module.exports = function(grunt) {
var yeomanConfig;
require("load-grunt-tasks")(grunt);
require("time-grunt")(grunt);
yeomanConfig = {
app: "client",
dist: "dist",
docs: "documentation"
};
try {
yeomanConfig.app = require("./bower.json").appPath || yeomanConfig.app;
} catch (_error) {}
grunt.initConfig({
yeoman: yeomanConfig,
serverJS: ["Gruntfile.js", "server.js", "config/**/*.js", "app/**/*.js"],
watch: {
express: {
files: [
"app/**/*.js",
"config/{,*/}*.js",
"server.js",
"Gruntfile.js"
],
tasks: "express:dev",
options: {
nospawn: true
}
},
compass: {
files: ["<%= yeoman.app %>/styles/**/*.{scss,sass}"],
tasks: ["compass:server"]
},
less: {
files: ["<%= yeoman.app %>/styles-less/**/*.less"],
tasks: ["less:server"]
},
jade: {
files: ["<%= yeoman.docs %>/jade/*.jade"],
tasks: ["jade:docs"]
},
livereload: {
options: {
livereload: LIVERELOAD_PORT
},
files: [
"<%= yeoman.app %>/index.html",
"<%= yeoman.app %>/app/**/*.html",
"<%= yeoman.app %>/app/**/*.js",
"<%= yeoman.app %>/styles/**/*.scss",
"<%= yeoman.app %>/styles-less/**/*.less",
".tmp/styles/**/*.css",
"<%= yeoman.app %>/images/**/*.{png,jpg,jpeg,gif,webp,svg}",
"<%= yeoman.docs %>/jade/*.jade"
]
}
},
express: {
server: {
options : {
port: 3000,
script: 'server.js'
}
}
},
connect: {
options: {
port: 5000,
hostname: "localhost"
},
livereload: {
options: {
middleware: function(connect) {
return [lrSnippet, mountFolder(connect, ".tmp"), mountFolder(connect, yeomanConfig.app)];
}
}
},
docs: {
options: {
middleware: function(connect) {
return [lrSnippet, mountFolder(connect, yeomanConfig.docs)];
}
}
},
test: {
options: {
middleware: function(connect) {
return [mountFolder(connect, ".tmp"), mountFolder(connect, "test")];
}
}
},
dist: {
options: {
middleware: function(connect) {
return [mountFolder(connect, yeomanConfig.dist)];
}
}
}
},
open: {
server: {
url: "http://localhost:<%= connect.options.port %>"
}
},
clean: {
dist: {
files: [
{
dot: true,
src: [".tmp", "<%= yeoman.dist %>/*", "!<%= yeoman.dist %>/.git*"]
}
]
},
all: [".tmp", ".sass-cache", "readme.md", "client/bower_components", "documentation/jade", "documentation/config.codekit", "landing/jade", "landing/config.codekit", "node_modules", ".git"],
server: ".tmp"
},
jshint: {
options: {
jshintrc: ".jshintrc"
},
all: ["Gruntfile.js", "<%= yeoman.app %>/scripts/**/*.js"]
},
injector: {
options: {
relative: true
},
local_dependencies: {
files: {
"<%= yeoman.app %>/index.html": [
"<%= yeoman.app %>/app/**/*.module.js",
"<%= yeoman.app %>/app/**/*.js",
"!" + "<%= yeoman.app %>/**/*.spec.js"
]
}
},
},
jade: {
docs: {
options: {
pretty: true
},
files: {
"<%= yeoman.docs %>/index.html": ["<%= yeoman.docs %>/jade/index.jade"]
}
}
},
compass: {
options: {
sassDir: "<%= yeoman.app %>/styles",
cssDir: ".tmp/styles",
generatedImagesDir: ".tmp/styles/ui/images/",
imagesDir: "<%= yeoman.app %>/styles/ui/images/",
javascriptsDir: "<%= yeoman.app %>/scripts",
fontsDir: "<%= yeoman.app %>/fonts",
importPath: "<%= yeoman.app %>/bower_components",
httpImagesPath: "styles/ui/images/",
httpGeneratedImagesPath: "styles/ui/images/",
httpFontsPath: "fonts",
relativeAssets: true
},
dist: {
options: {
outputStyle: 'compressed',
debugInfo: false,
noLineComments: true
}
},
server: {
options: {
debugInfo: true
}
},
forvalidation: {
options: {
debugInfo: false,
noLineComments: false
}
}
},
less: {
server: {
options: {
strictMath: true,
dumpLineNumbers: true,
sourceMap: true,
sourceMapRootpath: "",
outputSourceFiles: true
},
files: [
{
expand: true,
cwd: "<%= yeoman.app %>/styles-less",
src: "main.less",
dest: ".tmp/styles",
ext: ".css"
}
]
},
dist: {
options: {
cleancss: true,
report: 'min'
},
files: [
{
expand: true,
cwd: "<%= yeoman.app %>/styles-less",
src: "main.less",
dest: ".tmp/styles",
ext: ".css"
}
]
}
},
useminPrepare: {
html: "<%= yeoman.app %>/index.html",
options: {
dest: "<%= yeoman.dist %>",
flow: {
steps: {
js: ["concat"],
css: ["cssmin"]
},
post: []
}
}
},
usemin: {
html: ["<%= yeoman.dist %>/**/*.html", "!<%= yeoman.dist %>/bower_components/**"],
css: ["<%= yeoman.dist %>/styles/**/*.css"],
options: {
dirs: ["<%= yeoman.dist %>"]
}
},
htmlmin: {
dist: {
options: {},
files: [
{
expand: true,
cwd: "<%= yeoman.app %>",
src: ["*.html", "views/*.html"],
dest: "<%= yeoman.dist %>"
}
]
}
},
copy: {
dist: {
files: [
{
expand: true,
dot: true,
cwd: "<%= yeoman.app %>",
dest: "<%= yeoman.dist %>",
src: [
"favicon.ico",
"bower_components/font-awesome/css/*",
"bower_components/font-awesome/fonts/*",
"bower_components/weather-icons/css/*",
"bower_components/weather-icons/fonts/*",
"bower_components/weather-icons/font/*",
"fonts/**/*",
"i18n/**/*",
"images/**/*",
"styles/fonts/**/*",
"styles/img/**/*",
"styles/ui/images/*",
"app/**/*.html"
]
}, {
expand: true,
cwd: ".tmp",
dest: "<%= yeoman.dist %>",
src: ["styles/**", "assets/**"]
}, {
expand: true,
cwd: ".tmp/images",
dest: "<%= yeoman.dist %>/images",
src: ["generated/*"]
}
]
},
styles: {
expand: true,
cwd: "<%= yeoman.app %>/styles",
dest: ".tmp/styles/",
src: "**/*.css"
}
},
concurrent: {
server: ["compass:server", "copy:styles"],
dist: ["compass:dist", "copy:styles", "htmlmin"],
lessServer: ["less:server", "copy:styles"],
lessDist: ["less:dist", "copy:styles", "htmlmin"]
},
cssmin: {
options: {
keepSpecialComments: '0'
},
dist: {}
},
concat: {
options: {
separator: grunt.util.linefeed + ';' + grunt.util.linefeed
},
dist: {}
},
uglify: {
options: {
mangle: false,
compress: {
drop_console: true
}
},
dist: {
files: {
"<%= yeoman.dist %>/scripts/app.js": [".tmp/**/*.js", "<%= yeoman.app %>/scripts/**/*.js", "!<%= yeoman.app %>/scripts/vendors/**"]
}
}
}
});
grunt.registerTask("docs", function() {
return grunt.task.run(["jade:docs", "connect:docs", "open", "watch"]);
});
grunt.registerTask("server", function(target) {
if (target === "dist") {
return grunt.task.run(["serve:dist"]);
}
return grunt.task.run(["serve"]);
});
grunt.registerTask("serve", function(target) {
if (target === "dist") {
return grunt.task.run(["build", "open", "connect:dist:keepalive"]);
}
return grunt.task.run(["clean:server", "concurrent:server", "express:server", "connect:livereload", "open", "watch"]);
});
grunt.registerTask("build", ["clean:dist", "useminPrepare", "concurrent:dist", "copy:dist", "cssmin", "concat", "uglify", "usemin"]);
return grunt.registerTask("default", ["serve"]);
};
server.js
var express = require('express'),
fs = require('fs'),
passport = require('passport'),
mongoose = require('mongoose'),
http = require('http'),
app = express(),
server = require('http').createServer(app),
config = require('./config/environment'),
auth = require('./config/middlewares/authorization'),
models_path = __dirname + '/app/models',
routes_path = __dirname + '/app/routes';
fs.readdirSync(models_path).forEach(function (file) {
require(models_path + '/' + file);
});
app.set('port', process.env.OPENSHIFT_NODEJS_PORT || 3000);
app.set('ipaddr', process.env.OPENSHIFT_NODEJS_IP || 'localhost');
require('./config/express')(app, config, passport);
require('./config/passport')(passport, config);
fs.readdirSync(routes_path).forEach(function (file) {
require(routes_path + '/' + file)(app, passport, auth);
});
mongoose.connect(config.db);
server.listen(app.get('port'), app.get('ipaddr'), function(){
console.log('Express server listening on IP/hostname: "' + app.get('ipaddr') + '" and port: "' + app.get('port') + '"');
});

Ok. I solved it with grunt-connect-proxy. I added to connect task proxy and it finaly works. Here is all code of gruntfile:
"use strict";
var LIVERELOAD_PORT, lrSnippet, mountFolder, proxySnippet;
LIVERELOAD_PORT = 35728;
lrSnippet = require("connect-livereload")({
port: LIVERELOAD_PORT
});
mountFolder = function(connect, dir) {
return connect["static"](require("path").resolve(dir));
};
module.exports = function(grunt) {
var yeomanConfig;
proxySnippet = require("grunt-connect-proxy/lib/utils").proxyRequest;
require("load-grunt-tasks")(grunt);
require("time-grunt")(grunt);
yeomanConfig = {
app: "client",
dist: "dist",
docs: "documentation"
};
try {
yeomanConfig.app = require("./bower.json").appPath || yeomanConfig.app;
} catch (_error) {}
grunt.initConfig({
yeoman: yeomanConfig,
appFiles: {
serverJS: ["Gruntfile.js", "server.js", "config/{,*/}*.js", "app/**/*.js"]
},
watch: {
express: {
files: "<%= appFiles.serverJS %>",
tasks: "express:dev",
options: {
nospawn: true
}
},
compass: {
files: ["<%= yeoman.app %>/styles/**/*.{scss,sass}"],
tasks: ["compass:server"]
},
less: {
files: ["<%= yeoman.app %>/styles-less/**/*.less"],
tasks: ["less:server"]
},
jade: {
files: ["<%= yeoman.docs %>/jade/*.jade"],
tasks: ["jade:docs"]
},
livereload: {
options: {
livereload: LIVERELOAD_PORT
},
files: [
"<%= yeoman.app %>/index.html",
"<%= yeoman.app %>/app/**/*.html",
"<%= yeoman.app %>/app/**/*.js",
"<%= yeoman.app %>/styles/**/*.scss",
"<%= yeoman.app %>/styles-less/**/*.less",
".tmp/styles/**/*.css",
"<%= yeoman.app %>/images/**/*.{png,jpg,jpeg,gif,webp,svg}",
"<%= yeoman.docs %>/jade/*.jade"
]
}
},
express: {
server: {
options : {
port: 3000,
script: 'server.js'
}
}
},
connect: {
options: {
port: 5000,
hostname: "localhost"
},
proxies: [
{
context: "/",
host: "localhost",
port: 3000 + "",
https: false,
changeOrigin: false
}
],
livereload: {
options: {
middleware: function(connect) {
return [lrSnippet, mountFolder(connect, ".tmp"), mountFolder(connect, yeomanConfig.app), proxySnippet];
}
}
},
docs: {
options: {
middleware: function(connect) {
return [lrSnippet, mountFolder(connect, yeomanConfig.docs)];
}
}
},
test: {
options: {
middleware: function(connect) {
return [mountFolder(connect, ".tmp"), mountFolder(connect, "test")];
}
}
},
dist: {
options: {
middleware: function(connect) {
return [mountFolder(connect, yeomanConfig.dist)];
}
}
}
},
open: {
server: {
url: "http://localhost:<%= connect.options.port %>"
}
},
clean: {
dist: {
files: [
{
dot: true,
src: [".tmp", "<%= yeoman.dist %>/*", "!<%= yeoman.dist %>/.git*"]
}
]
},
all: [".tmp", ".sass-cache", "readme.md", "client/bower_components", "documentation/jade", "documentation/config.codekit", "landing/jade", "landing/config.codekit", "node_modules", ".git"],
server: ".tmp"
},
jshint: {
options: {
jshintrc: ".jshintrc"
},
all: ["Gruntfile.js", "<%= yeoman.app %>/scripts/**/*.js"]
},
injector: {
options: {
relative: true
},
local_dependencies: {
files: {
"<%= yeoman.app %>/index.html": [
"<%= yeoman.app %>/app/**/*.module.js",
"<%= yeoman.app %>/app/**/*.js",
"!" + "<%= yeoman.app %>/**/*.spec.js"
]
}
},
},
jade: {
docs: {
options: {
pretty: true
},
files: {
"<%= yeoman.docs %>/index.html": ["<%= yeoman.docs %>/jade/index.jade"]
}
}
},
compass: {
options: {
sassDir: "<%= yeoman.app %>/styles",
cssDir: ".tmp/styles",
generatedImagesDir: ".tmp/styles/ui/images/",
imagesDir: "<%= yeoman.app %>/styles/ui/images/",
javascriptsDir: "<%= yeoman.app %>/scripts",
fontsDir: "<%= yeoman.app %>/fonts",
importPath: "<%= yeoman.app %>/bower_components",
httpImagesPath: "styles/ui/images/",
httpGeneratedImagesPath: "styles/ui/images/",
httpFontsPath: "fonts",
relativeAssets: true
},
dist: {
options: {
outputStyle: 'compressed',
debugInfo: false,
noLineComments: true
}
},
server: {
options: {
debugInfo: true
}
},
forvalidation: {
options: {
debugInfo: false,
noLineComments: false
}
}
},
less: {
server: {
options: {
strictMath: true,
dumpLineNumbers: true,
sourceMap: true,
sourceMapRootpath: "",
outputSourceFiles: true
},
files: [
{
expand: true,
cwd: "<%= yeoman.app %>/styles-less",
src: "main.less",
dest: ".tmp/styles",
ext: ".css"
}
]
},
dist: {
options: {
cleancss: true,
report: 'min'
},
files: [
{
expand: true,
cwd: "<%= yeoman.app %>/styles-less",
src: "main.less",
dest: ".tmp/styles",
ext: ".css"
}
]
}
},
useminPrepare: {
html: "<%= yeoman.app %>/index.html",
options: {
dest: "<%= yeoman.dist %>",
flow: {
steps: {
js: ["concat"],
css: ["cssmin"]
},
post: []
}
}
},
usemin: {
html: ["<%= yeoman.dist %>/**/*.html", "!<%= yeoman.dist %>/bower_components/**"],
css: ["<%= yeoman.dist %>/styles/**/*.css"],
options: {
dirs: ["<%= yeoman.dist %>"]
}
},
htmlmin: {
dist: {
options: {},
files: [
{
expand: true,
cwd: "<%= yeoman.app %>",
src: ["*.html", "views/*.html"],
dest: "<%= yeoman.dist %>"
}
]
}
},
copy: {
dist: {
files: [
{
expand: true,
dot: true,
cwd: "<%= yeoman.app %>",
dest: "<%= yeoman.dist %>",
src: [
"favicon.ico",
"bower_components/font-awesome/css/*",
"bower_components/font-awesome/fonts/*",
"bower_components/weather-icons/css/*",
"bower_components/weather-icons/fonts/*",
"bower_components/weather-icons/font/*",
"fonts/**/*",
"i18n/**/*",
"images/**/*",
"styles/fonts/**/*",
"styles/img/**/*",
"styles/ui/images/*",
"app/**/*.html"
]
}, {
expand: true,
cwd: ".tmp",
dest: "<%= yeoman.dist %>",
src: ["styles/**", "assets/**"]
}, {
expand: true,
cwd: ".tmp/images",
dest: "<%= yeoman.dist %>/images",
src: ["generated/*"]
}
]
},
styles: {
expand: true,
cwd: "<%= yeoman.app %>/styles",
dest: ".tmp/styles/",
src: "**/*.css"
}
},
concurrent: {
server: ["compass:server", "copy:styles"],
dist: ["compass:dist", "copy:styles", "htmlmin"],
lessServer: ["less:server", "copy:styles"],
lessDist: ["less:dist", "copy:styles", "htmlmin"]
},
cssmin: {
options: {
keepSpecialComments: '0'
},
dist: {}
},
concat: {
options: {
separator: grunt.util.linefeed + ';' + grunt.util.linefeed
},
dist: {}
},
uglify: {
options: {
mangle: false,
compress: {
drop_console: true
}
},
dist: {
files: {
"<%= yeoman.dist %>/scripts/app.js": [".tmp/**/*.js", "<%= yeoman.app %>/scripts/**/*.js", "!<%= yeoman.app %>/scripts/vendors/**"]
}
}
}
});
grunt.registerTask("docs", function() {
return grunt.task.run(["jade:docs", "connect:docs", "open", "watch"]);
});
grunt.registerTask("server", function(target) {
if (target === "dist") {
return grunt.task.run(["serve:dist"]);
}
return grunt.task.run(["serve"]);
});
grunt.registerTask("serve", function(target) {
if (target === "dist") {
return grunt.task.run(["build", "open", "connect:dist:keepalive"]);
}
return grunt.task.run(["clean:server", "concurrent:server", "configureProxies", "express:server", "connect:livereload", "open", "watch"]);
});
grunt.registerTask("build", ["clean:dist", "useminPrepare", "concurrent:dist", "copy:dist", "cssmin", "concat", "uglify", "usemin"]);
return grunt.registerTask("default", ["serve"]);
};

Related

Grunt app deployed on Heroku ... and what's next ?... my app doesn't start

I have a basic node app with gruntfile and I had some pains to make the deploy. So I did a new grunt task, did some changes.
The deploy then is fine.
But now when I go to my app. I have a blank page.
It doesn't load the appConfig.app dir.
I probably miss something big I couldn't figure out. I thought grunt connect would do the wire but it seems server.js is waiting something.
NB : I think I don't need Express here.
Below are different files :
gruntfile.js
server.js
package.js
Gruntfile.js
'use strict';
module.exports = function (grunt) {
require('load-grunt-tasks')(grunt);
require('time-grunt')(grunt);
var modRewrite = require('connect-modrewrite');
// Configurable paths for the application
var appConfig = {
app: require('./bower.json').appPath || 'app',
dist: 'dist'
};
//Environment vars
var envConfig = {
dev: {
//baseUrl: 'http://localhost:3000',
loginUrl: 'http://demo.lvh.me:9000',
uploadUrl: 'anuploadurl/upload'
},
prod: {
baseUrl: 'http://aprodurl',
loginUrl: 'an herokuapp url'
}
};
// Define the configuration for all the tasks
grunt.initConfig({
appConf: appConfig,
// Empties folders to start fresh
clean: {
dist: {
files: [{
dot: true,
src: [
'.tmp',
'<%= appConf.dist %>/{,*/}*',
'!<%= appConf.dist %>/.git*'
]
}],
options: {
force: true //since dist directory is outside, we must use force flag.
}
},
server: '.tmp'
},
//server settings
ngconstant: {
// Options for all targets
options: {
space: ' ',
wrap: '\'use strict\';\n\n {%= __ngModule %}',
name: 'config'
},
// Environment targets
development: {
options: {
dest: 'app/config.js'
},
constants: envConfig.dev
},
production: {
options: {
dest: '<%= appConf.app %>/config.js'
},
constants: envConfig.prod
}
},
// Automatically inject Bower components into the app
wiredep: {
app: {
src: ['<%= appConf.app %>/index.html'],
ignorePath: /\.\.\//,
'options': {
'overrides': {
'semantic-ui': {
'main': ['dist/semantic.css', 'dist/semantic.js']
}
}
}
}
},
// Copies remaining files to places other tasks can use
copy: {
dist: {
files: [{
expand: true,
dot: true,
cwd: '<%= appConf.app %>/*',
dest: '<%= appConf.dist %>',
src: [
'*.{ico,png,txt}',
'{,*/}*.html',
'images/{,*/}*.{webp}',
'fonts/*'
]
}, {
expand: true,
cwd: '<%= appConf.app %>/images',
dest: '<%= appConf.dist %>/images',
src: ['generated/*']
}, { // not in use
expand: true,
cwd: 'bower_components/font-awesome',
src: 'fonts/*',
dest: '<%= appConf.dist %>'
}]
},
styles: {
files: [
{
expand: true,
cwd: '<%= appConf.app %>/*',
dest: '<%= appConf.dist %>/styles',
src: '{,*/}*.css'
}
]
}
},
// Run some tasks in parallel to speed up the build process
concurrent: {
server: [
'copy:styles'
],
test: [
'copy:styles'
],
dist: [
'copy:styles',
'svgmin'
]
},
// Add vendor prefixed styles
autoprefixer: {
options: {
browsers: ['last 1 version']
},
dist: {
files: [{
expand: true,
cwd: '<%= appConf.app %>/*',
src: '{,*/}*.css',
dest: '<%= appConf.dist %>/styles/'
}]
}
},
// The actual grunt server settings
connect: {
options: {
port: 9000,
// Change this to '0.0.0.0' to access the server from outside.
hostname: '0.0.0.0',
livereload: 35729
},
livereload: {
options: {
open: true,
middleware: function (connect) {
return [
modRewrite(['^[^\\.]*$ /index.html [L]']),
connect.static('.tmp'),
connect().use(
'/bower_components',
connect.static('./bower_components')
),
connect.static(appConfig.app)
];
}
}
},
test: {
options: {
port: 9001,
middleware: function (connect) {
return [
rewriteRulesSnippet,
connect.static('.tmp'),
connect.static('test'),
connect().use(
'/bower_components',
connect.static('./bower_components')
),
connect.static(appConfig.app)
];
}
}
},
dist: {
options: {
port:process.env.PORT,
open: true,
base: '<%= appConf.app %>'
}
}
},
// Make sure code styles are up to par and there are no obvious mistakes
jshint: {
options: {
jshintrc: '.jshintrc',
reporter: require('jshint-stylish')
},
all: {
src: [
'Gruntfile.js',
'server.js',
'<%= appConf.app %>/{,*/}*.js'
]
}
},
// Watches files for changes and runs tasks based on the changed files
watch: {
bower: {
files: ['bower.json'],
tasks: ['wiredep']
},
js: {
files: ['<%= appConf.app %>/{,**/}*.js'],
tasks: ['newer:jshint:all'],
options: {
livereload: '<%= connect.options.livereload %>'
}
},
css: {
files: ['<%= appConf.app %>/styles/{,**/}*.scss'],
tasks: ['sass'],
options: {
livereload: true,
},
},
styles: {
files: [
'<%= appConf.app %>/styles/{,**/}*.css',
'<%= appConf.app %>/../templating/css/style.css'
],
tasks: ['newer:copy:styles', 'autoprefixer']
},
gruntfile: {
files: ['Gruntfile.js']
},
livereload: {
options: {
livereload: '<%= connect.options.livereload %>'
},
files: [
'<%= appConf.app %>/{,**/}*.html',
'.tmp/styles/{,**/}*.css',
'<%= appConf.app %>/images/{,**/}*.{png,jpg,jpeg,gif,webp,svg}'
]
}
},
sass: {
dev: {
options: {
style: 'expanded'
},
files: [
{
expand: true,
cwd: '<%= appConf.app %>/styles',
src: ['*.scss'],
ext: '.css',
dest: '<%= appConf.dist %>/styles'
}
]
}
}
});
grunt.loadNpmTasks('grunt-sass');
// Build the development application
grunt.registerTask('serve', 'Compile then start a connect web server', function () {
grunt.task.run([
'clean:server',
'ngconstant:development',
'wiredep',
'sass',
'concurrent:server',
'autoprefixer',
'connect:livereload',
'watch'
]);
});
// Build the production application
grunt.registerTask('build', 'Compile app on production settings', function () {
grunt.task.run([
'clean:server',
'ngconstant:production',
'wiredep',
'sass',
'concurrent:server',
'autoprefixer',
'connect:dist'
]);
});
};
server.js
var http = require('http');
var port = process.env.PORT || 80;
http.createServer(function (req, res) {
res.writeHead(200, {
'Content-Type': 'text/html',
'Access-Control-Allow-Origin' : '*'
});
//res.end('app/index.html');
}).listen(port);
console.log('Server running at port '+port);
package.json
{
"private": true,
"engines": {
"node": "4.2.2"
},
"scripts": {
"postinstall": "bower install && grunt build",
"start": "node server.js"
},
"dependencies": { all the dependancies .... }
}
It was a huge and harsh debugging but I finally found out.
It was coming from multiple mistakes and bugs I had :
the node server.js is useless
I invstigated on the grunt connect method and created a production setup
I splitted the grunt serve into a grunt build task and a webconnect task
Then updated package.json file
Very important for heroku : in Gruntfile.js on the connect object :
dist: {
options: {
port:process.env.PORT, #<=== need to have a dynamic port env for Heroku deployment
open: true,
base: '<%= appConf.dist %>'
}
}
here are the grunt tasks added :
// Build the production application
grunt.registerTask('build', 'Compile on dist folder', function () {
grunt.task.run([
'clean:dist',
'ngconstant:production',
'wiredep',
'sass',
'concurrent:dist',
'autoprefixer:dist'
]);
});
// Build the production application
grunt.registerTask('webconnect', 'connect web server', function () {
grunt.task.run([
'connect:dist'
]);
});
then on package.json :
"scripts": {
"postinstall": "bower install && grunt build",
"start": "grunt webconnect"
}

how to modify a grunt config file to work with iss

I am using a template that came with grunt. it works great, it watches for changes and recompiles and reload page on save. I have been using it with a seperate webapi project, but cors has been giving me problems and i would like to combine the projects. I dont want to lose the livereload function of grunt. currently it is tied in with the node server. I will be running it with iis express so I need to change the config file. how do i do this? the iss port will be 28713
'use strict';
module.exports = function (grunt) {
// Load grunt tasks automatically
require('load-grunt-tasks')(grunt);
// Show grunt task time
require('time-grunt')(grunt);
// Configurable paths for the app
var appConfig = {
app: 'app',
dist: 'dist'
};
// Grunt configuration
grunt.initConfig({
// Project settings
homer: appConfig,
// The grunt server settings
connect: {
options: {
port: 9000,
hostname: 'localhost',
livereload: 35729
},
livereload: {
options: {
open: true,
middleware: function (connect) {
return [
connect.static('.tmp'),
connect().use(
'/bower_components',
connect.static('./bower_components')
),
connect().use(
'/vendors',
connect.static('./vendors')
),
connect.static(appConfig.app)
];
}
}
},
dist: {
options: {
open: true,
base: '<%= homer.dist %>'
}
}
},
// Compile less to css
less: {
development: {
options: {
compress: true,
optimization: 2
},
files: {
"app/styles/style.css": "app/less/style.less"
}
}
},
// Watch for changes in live edit
watch: {
styles: {
files: ['app/less/**/*.less'],
tasks: ['less', 'copy:styles'],
options: {
nospawn: true,
livereload: '<%= connect.options.livereload %>'
},
},
js: {
files: [
'<%= homer.app %>/scripts/{,*/}*.js',
'<%= homer.app %>/js/{,*/}*.js'
],
options: {
livereload: '<%= connect.options.livereload %>'
}
},
livereload: {
options: {
livereload: '<%= connect.options.livereload %>'
},
files: [
'<%= homer.app %>/**/*.html',
'.tmp/styles/{,*/}*.css',
'<%= homer.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'
]
}
},
uglify: {
options: {
mangle: false
}
},
// Clean dist folder
clean: {
dist: {
files: [{
dot: true,
src: [
'.tmp',
'<%= homer.dist %>/{,*/}*',
'!<%= homer.dist %>/.git*'
]
}]
},
server: '.tmp'
},
// Copies remaining files to places other tasks can use
copy: {
dist: {
files: [
{
expand: true,
dot: true,
cwd: '<%= homer.app %>',
dest: '<%= homer.dist %>',
src: [
'*.{ico,png,txt}',
'.htaccess',
'*.html',
'views/{,*/}*.html',
'styles/img/*.*',
'images/{,*/}*.*'
]
},
{
expand: true,
dot: true,
cwd: 'bower_components/fontawesome',
src: ['fonts/*.*'],
dest: '<%= homer.dist %>'
},
{
expand: true,
dot: true,
cwd: 'bower_components/bootstrap',
src: ['fonts/*.*'],
dest: '<%= homer.dist %>'
},
{
expand: true,
dot: true,
cwd: 'app/fonts/pe-icon-7-stroke/',
src: ['fonts/*.*'],
dest: '<%= homer.dist %>'
},
]
},
styles: {
expand: true,
cwd: '<%= homer.app %>/styles',
dest: '.tmp/styles/',
src: '{,*/}*.css'
}
},
// Renames files for browser caching purposes
filerev: {
dist: {
src: [
'<%= homer.dist %>/js/{,*/}*.js',
'<%= homer.dist %>/scripts/{,*/}*.js',
'<%= homer.dist %>/styles/{,*/}*.css',
'<%= homer.dist %>/styles/fonts/*'
]
}
},
htmlmin: {
dist: {
options: {
collapseWhitespace: true,
conservativeCollapse: true,
collapseBooleanAttributes: true,
removeCommentsFromCDATA: true,
removeOptionalTags: true
},
files: [{
expand: true,
cwd: '<%= homer.dist %>',
src: ['*.html', 'views/{,*/}*.html'],
dest: '<%= homer.dist %>'
}]
}
},
useminPrepare: {
html: 'app/index.html',
options: {
dest: 'dist'
}
},
usemin: {
html: ['dist/index.html']
}
});
grunt.registerTask('live', [
'clean:server',
'copy:styles',
'connect:livereload',
'watch'
]);
grunt.registerTask('server', [
'build',
'connect:dist:keepalive'
]);
grunt.registerTask('build', [
'clean:dist',
'less',
'useminPrepare',
'concat',
'copy:dist',
'cssmin',
'uglify',
'filerev',
'usemin',
'htmlmin'
]);
};

Grunt-injector - Handling Multiple Targets

I'm new to grunt so I apologize if this question is a little silly.
I've got the following grunt file I've inherited and been modifying/updating:
'use strict';
module.exports = function (grunt) {
require('load-grunt-tasks')(grunt);
require('time-grunt')(grunt);
var getVersion = function(){
var thisVer = require('./bower.json').version || '0.0.0';
var nextVer = '';
var nextVerList = thisVer.split('.');
var nextPatch = new String(new Number(nextVerList.pop()) + 1);
nextVerList.push(nextPatch);
nextVer = nextVerList.join('.');
return nextVer;
}
grunt.initConfig({
yeoman: { app: require('./bower.json').appPath || 'app',
dist: 'dist',
quickdist: 'release-quick',
version: getVersion()
},
clean: {
dist: {
force : true,
files: [{
dot: true,
src: [
'.tmp',
'<%= yeoman.dist %>/*',
'!<%= yeoman.dist %>/.git*'
]
}]
}
},
// Put files not handled in other tasks here
copy: {
dist: {
files: [{
expand: true,
dot: true,
cwd: '<%= yeoman.app %>',
dest: '<%= yeoman.dist %>',
src: [
'*.{ico,png,txt}',
'.htaccess',
'*.html',
'views/{,**/}*.html',
'lib/**/*',
'images/{,*/}*.{gif,webp}',
'styles/fonts/*'
]
}, {
expand: true,
cwd: '.tmp/images',
dest: '<%= yeoman.dist %>/images',
src: [
'generated/*'
]
}]
}
},
compass: {
options: {
sassDir: '<%= yeoman.app %>/scss',
cssDir: '<%= yeoman.app %>/styles',
generatedImagesDir: '<%= yeoman.app %>/images/generated',
imagesDir: '<%= yeoman.app %>/images',
javascriptsDir: '<%= yeoman.app %>/scripts',
fontsDir: '<%= yeoman.app %>/fonts',
importPath: '<%= yeoman.app %>/lib',
require: [ 'bootstrap-sass', 'compass/import-once/activate' ],
httpImagesPath: '/images',
httpGeneratedImagesPath: '/images/generated',
httpFontsPath: '/fonts',
relativeAssets: true
},
clean: {
options: {
clean: true,
trace: true,
force: true,
debugInfo: false
}
},
dist: {
options: {
debugInfo: false,
trace: true
}
}
},
autoprefixer: {
options: ['last 1 version'],
dist: {
files: [{
expand: true,
cwd: '<%= yeoman.app %>/styles/',
src: '{,*/}*.css',
dest: '<%= yeoman.app %>/styles/'
}]
}
},
cssmin: {
dist: {
files: {
'<%= yeoman.dist %>/styles/styles.css': [
'.tmp/styles/{,*/}*.css',
'<%= yeoman.app %>/styles/{,*/}*.css'
]
}
}
},
imagemin: {
dist: {
files: [{
expand: true,
cwd: '<%= yeoman.app %>/images',
src: '{,*/}*.{png,jpg,jpeg}',
dest: '<%= yeoman.dist %>/images'
}]
}
},
svgmin: {
dist: {
files: [{
expand: true,
cwd: '<%= yeoman.app %>/images',
src: '{,*/}*.svg',
dest: '<%= yeoman.dist %>/images'
}]
}
},
ngAnnotate: {
dist: {
files: [
{
dest: '.tmp/scripts/scripts.js',
src: ['app/scripts/**/*.js'],
}
]
}
},
uglify: {
all_src : {
options : {
mangleProperties: false,
sourceMap : false,
},
files: [
{
dest : 'dist/scripts/scripts.min.js',
src: [ '.tmp/scripts/**/*.js', 'app/scripts/**/*.js' ],
},
{
expand: true,
cwd: 'app/js/',
src: ['*.js', '!*.min.js'],
dest: 'dist/js/',
ext: '.min.js'
}
]
}
},
injector: {
options: {
ignorePath: 'app/', // strips 'app/' from the urls of files
"addRootSlash": false // strips leading '/' from path files
},
local_dependencies: {
files: {
'<%= yeoman.app %>/index.html': [
'<%= yeoman.app %>/scripts/**/*.js',
'<%= yeoman.app %>/styles/**/*.css'],
}
},
bower_dependencies: {
options: {
starttag: '<!-- injector:bower:{{ext}} -->'
},
files: {
'<%= yeoman.app %>/index.html': 'bower.json'
}
}
},
});
grunt.registerTask('build', function (target) {
var preTasks = [], postTasks = [];
var baseTasks = [ 'compass:clean', 'compass:dist','autoprefixer'];
switch(target){
case 'dist':
preTasks = [ 'clean:dist' ];
postTasks = [ 'cssmin', 'imagemin', 'svgmin', 'ngAnnotate', 'uglify', 'copy:dist', 'injector:dist' ];
break;
case 'dev':
default:
preTasks = [ ];
postTasks = [ 'injector' ];
break;
}
var tasks = preTasks.concat(baseTasks).concat(postTasks);
console.log(tasks);
return grunt.task.run(tasks);
});
grunt.registerTask('default', [
'build:dev'
]);
grunt.registerTask('build-dist', [
'build:dist'
]);
/*
grunt.registerTask('build', [
'clean:dist',
'compass:clean',
'compass:dist',
'copy:styles',
'imagemin',
'svgmin',
'injector',
'autoprefixer',
'ngAnnotate',
'copy:dist',
'cssmin',
'uglify',
'htmlmin'
]);//*/
};
I'm trying to get "injector" to run on yeoman.app if the task is dev, based on the folders in the app folder, and on yeoman.dist if the task is prod, based the folders in the dist folder.
The problem I'm running into is it doesn't appear I can create a sub-item under the injector configuration one for app, one for dist, so I run it with:
injector:app
or
injector:dist
As a result the value in the config seems stuck on what it was when the config was set.
What's the proper way to handle this?
Figured it out. Add a var to the config, use that var in the injector code, and set that var prior to running the task list:
'use strict';
module.exports = function (grunt) {
require('load-grunt-tasks')(grunt);
require('time-grunt')(grunt);
var getVersion = function(){
var thisVer = require('./bower.json').version || '0.0.0';
var nextVer = '';
var nextVerList = thisVer.split('.');
var nextPatch = new String(new Number(nextVerList.pop()) + 1);
nextVerList.push(nextPatch);
nextVer = nextVerList.join('.');
return nextVer;
}
var yeomanConfig = { app: require('./bower.json').appPath || 'app',
dist: 'dist',
quickdist: 'release-quick',
version: getVersion()
}
grunt.initConfig({
yeoman: yeomanConfig,
injectorTarget : yeomanConfig.app,
clean: {
dist: {
force : true,
files: [{
dot: true,
src: [
'.tmp',
'<%= yeoman.dist %>/*',
'!<%= yeoman.dist %>/.git*'
]
}]
}
},
// Put files not handled in other tasks here
copy: {
dist: {
files: [{
expand: true,
dot: true,
cwd: '<%= yeoman.app %>',
dest: '<%= yeoman.dist %>',
src: [
'*.{ico,png,txt}',
'.htaccess',
'*.html',
'views/{,**/}*.html',
'lib/**/*',
'images/{,*/}*.{gif,webp}',
'styles/fonts/*'
]
}, {
expand: true,
cwd: '.tmp/images',
dest: '<%= yeoman.dist %>/images',
src: [
'generated/*'
]
}]
}
},
compass: {
options: {
sassDir: '<%= yeoman.app %>/scss',
cssDir: '<%= yeoman.app %>/styles',
generatedImagesDir: '<%= yeoman.app %>/images/generated',
imagesDir: '<%= yeoman.app %>/images',
javascriptsDir: '<%= yeoman.app %>/scripts',
fontsDir: '<%= yeoman.app %>/fonts',
importPath: '<%= yeoman.app %>/lib',
require: [ 'bootstrap-sass', 'compass/import-once/activate' ],
httpImagesPath: '/images',
httpGeneratedImagesPath: '/images/generated',
httpFontsPath: '/fonts',
relativeAssets: true
},
clean: {
options: {
clean: true,
trace: true,
force: true,
debugInfo: false
}
},
dist: {
options: {
debugInfo: false,
trace: true
}
}
},
autoprefixer: {
options: ['last 1 version'],
dist: {
files: [{
expand: true,
cwd: '<%= yeoman.app %>/styles/',
src: '{,*/}*.css',
dest: '<%= yeoman.app %>/styles/'
}]
}
},
cssmin: {
dist: {
files: {
'<%= yeoman.dist %>/styles/styles.css': [
'.tmp/styles/{,*/}*.css',
'<%= yeoman.app %>/styles/{,*/}*.css'
]
}
}
},
imagemin: {
dist: {
files: [{
expand: true,
cwd: '<%= yeoman.app %>/images',
src: '{,*/}*.{png,jpg,jpeg}',
dest: '<%= yeoman.dist %>/images'
}]
}
},
svgmin: {
dist: {
files: [{
expand: true,
cwd: '<%= yeoman.app %>/images',
src: '{,*/}*.svg',
dest: '<%= yeoman.dist %>/images'
}]
}
},
ngAnnotate: {
dist: {
files: [
{
dest: '.tmp/scripts/scripts.js',
src: ['app/scripts/**/*.js'],
}
]
}
},
uglify: {
all_src : {
options : {
mangleProperties: false,
sourceMap : false,
},
files: [
{
dest : 'dist/scripts/scripts.min.js',
src: [ '.tmp/scripts/**/*.js', 'app/scripts/**/*.js' ],
},
{
expand: true,
cwd: 'app/js/',
src: ['*.js', '!*.min.js'],
dest: 'dist/js/',
ext: '.min.js'
}
]
}
},
injector: {
options: {
ignorePath: '<%= injectorTarget %>/', // strips 'app/' from the urls of files
"addRootSlash": false // strips leading '/' from path files
},
local_dependencies: {
files: {
'<%= injectorTarget %>/index.html': [
'<%= injectorTarget %>/scripts/**/*.js',
'<%= injectorTarget %>/styles/**/*.css'],
}
},
bower_dependencies: {
options: {
starttag: '<!-- injector:bower:{{ext}} -->'
},
files: {
'<%= injectorTarget %>/index.html': 'bower.json'
}
}
},
});
grunt.registerTask('build', function (target) {
var preTasks = [], postTasks = [];
var baseTasks = [ 'compass:clean', 'compass:dist','autoprefixer'];
var baseTasks = [];
switch(target){
case 'prod':
grunt.config.set("injectorTarget", yeomanConfig.dist);
//preTasks = [ 'clean:dist' ];
//postTasks = [ 'cssmin', 'imagemin', 'svgmin', 'ngAnnotate', 'uglify', 'copy:dist', 'injector' ];
postTasks = [ 'injector' ];
break;
case 'dev':
default:
grunt.config.set("injectorTarget", yeomanConfig.app);
preTasks = [ ];
postTasks = [ 'injector' ];
break;
}
var tasks = preTasks.concat(baseTasks).concat(postTasks);
console.log(tasks);
return grunt.task.run(tasks);
});
grunt.registerTask('default', [
'build:dev'
]);
grunt.registerTask('Serve-Prod', [
'build:prod'
]);
/*
grunt.registerTask('build', [
'clean:dist',
'compass:clean',
'compass:dist',
'copy:styles',
'imagemin',
'svgmin',
'injector',
'autoprefixer',
'ngAnnotate',
'copy:dist',
'cssmin',
'uglify',
'htmlmin'
]);//*/
};

Grunt Serve - express:dev task gets stuck

I'm having issues with my grunt serve task. It seems to hang when it gets to the express:dev task;
Running "express:dev" (express) task
Starting background Express server
Debugger listening on port 5858
This an existing project where grunt serve used to work fine. This issue started yesterday when my Mac ran out of power mid process; in my head its either that or I have inadvertently changed something and broken it just before the mac went down and the power thing is just coincidence.
Has anyone got any ideas?
'use strict';
module.exports = function(grunt) {
require('load-grunt-tasks')(grunt);
var deploySettings = grunt.file.readJSON('config.json'),
deploy = deploySettings.production;
var useminSettings = []
var appConfig = {
app: require('./bower.json').appPath || 'app',
dist: 'dist' //require('./bower.json').distPath ||
};
grunt.initConfig({
mainApp: appConfig,
express: {
options: {
port: process.env.PORT || 9000
},
dev: {
options: {
script: 'app.js',
debug: true,
node_env: 'development',
livereload:true,
serverreload: true
}
},
prod: {
options: {
script: 'dist/app.js',
node_env: 'production'
}
}
},
watch: {
bower: {
files: ['bower.json'],
tasks: ['wiredep']
},
js : {
files: ['<%= mainApp.app %>/js/**/*.js'],
tasks: ['newer:jshint:all'],
options: {
livereload: true //'<%= connect.options.livereload %>'
}
},
gruntfile: {
files: ['Gruntfile.js']
},
less: {
files: ['<%= mainApp.app %>/css/**/*.less'],
tasks: ['less:development']
},
livereload: {
options: {
livereload : true //'<%= connect.options.livereload %>'
},
files: [
'<%= mainApp.app %>/**/*.html',
'<%= mainApp.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'
]
},
express: {
files: [
'server/**/*.{js,json}'
],
tasks: ['less:development','express:dev', 'wait'],
options: {
livereload: true,
nospawn: true //Without this option specified express won't be reloaded
}
}
},
// The actual grunt server settings
/*
connect: {
options: {
port: 9000,
// Change this to '0.0.0.0' to access the server from outside.
hostname: '0.0.0.0',
livereload: 35729
},
livereload: {
options: {
open: true,
middleware: function (connect) {
return [
connect.static('.tmp'),
connect().use(
'/bower_components',
connect.static('./bower_components')
),
connect.static(appConfig.app)
];
}
}
}
},
*/
// Automatically inject Bower components into the app
wiredep: {
app: {
src: ['<%= mainApp.app %>/index.html']
//ignorePath: /\.\.\//
}
},
// Make sure code styles are up to par and there are no obvious mistakes
jshint: {
options: {
jshintrc: '.jshintrc',
reporter: require('jshint-stylish')
},
all: {
src: [
'Gruntfile.js',
'<%= mainApp.app %>/js/{,*/}*.js'
]
}
},
//compiles our less down
less : {
development:{
options:{
path: '<%= mainApp.app %>/css/main.less',
rootPath: '/css/',
relativeUrls: false
},
files: {
'<%= mainApp.app %>/css/main.css' : '<%= mainApp.app %>/css/main.less'
}
}
},
// Empties folders to start fresh
clean: {
dist: {
files: [{
dot: true,
src : [
'.tmp',
'<%= mainApp.dist %>/{,*/}*',
'<%= mainApp.dist %>/.git*'
]
}]
},
server: '.tmp'
},
// Reads HTML for usemin blocks to enable smart builds that automatically
// concat, minify and revision files. Creates configurations in memory so
// additional tasks can operate on them
useminPrepare: {
html: '<%= mainApp.app %>/index.html',
options: {
dest: '<%= mainApp.dist %>/public',
flow: {
html: {
steps: {
js: ['concat', 'uglifyjs'],
css: ['cssmin']
},
post: {}
}
}
}
},
// Add vendor prefixed styles
autoprefixer: {
options: {
browsers: ['last 1 version']
},
dist: {
files: [{
expand: true,
cwd: '.tmp/styles/',
src: '{,*/}*.css',
dest: '<%= mainApp.dist %>/public/styles/'
}]
}
},
// ng-annotate tries to make the code safe for minification automatically
// by using the Angular long form for dependency injection.
ngAnnotate: {
dist: {
files: [{
expand: true,
cwd: '.tmp/concat/scripts',
src: ['*.js'],
dest: '.tmp/concat/scripts'
}]
}
},
//copies remaining files to places other tasks can use
copy: {
dist: {
files: [{
expand: true,
dot: true,
cwd: '<%= mainApp.app %>',
dest: '<%= mainApp.dist %>/public',
src:[
'*.html',
'views/partials/{,*/}*.html',
'static/img/{,*/}*.{png,jpg,jpeg,gif,ico,svg}',
'css/fonts/{,*/}*.{ttf,woff,eot,otf}'
]
}, {
expand: true,
cwd: '.tmp/images',
dest: '<%= mainApp.dist %>/public/images',
src: ['generated/*']
}, {
expand: true,
cwd: 'public/bower_components/bootstrap/dist',
src: 'fonts/{,*/}*.{ttf,woff,eot,otf}',
dest: '<%= mainApp.dist %>/public'
}, {
expand: true,
dest: '<%= mainApp.dist %>',
src: [
'app.js',
'package.json',
'server/**/*'
]
}]
},
debug: {
files: [{
expand: true,
dot: true,
cwd: '<%= mainApp.app %>',
dest: '<%= mainApp.dist %>',
src:[
'*.html',
'views/partials/{,*/}*.html',
'js/{,*/}*.js',
'css/{,*/}*.css',
'static/img/{,*/}*.{png,jpg,jpeg,gif}',
'css/fonts/{,*/}*.{ttf,woff,eot,otf}'
]
}, {
expand: true,
cwd: '.tmp/images',
dest: '<%= mainApp.dist %>/images',
src: ['generated/*']
}, {
expand: true,
cwd: 'public/bower_components/bootstrap/dist',
src: 'fonts/{,*/}*.{ttf,woff,eot,otf}',
dest: '<%= mainApp.dist %>'
}]
},
styles : {
expand: true,
cwd: '<%= mainApp.app %>/styles',
dest: '.tmp/styles',
src: '{,*/}*.css'
}
},
// Run some tasks in parallel to speed up the build process
concurrent: {
dist:[
'copy:styles'
]
},
// Replace Google CDN references
cdnify: {
dist: {
html: ['<%= mainApp.dist %>/public/*.html']
}
},
// Renames files for browser caching purposes
filerev: {
dist: {
src: [
'<%= mainApp.dist %>/public/scripts/{,*/}*.js',
'<%= mainApp.dist %>/public/styles/{,*/}*.css'
// '<%= yeoman.dist %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}',
// '<%= yeoman.dist %>/styles/fonts/*'
]
}
},
// Performs rewrites based on filerev and the useminPrepare configuration
usemin: {
html: ['<%= mainApp.dist %>/public/{,*/}*.html'],
css: ['<%= mainApp.dist %>/public/styles/{,*/}*.css'],
options: {
assetsDirs: ['<%= mainApp.dist %>/public']
}
},
htmlmin: {
dist: {
options: {
collapseWhitespace: true,
conservativeCollapse: true,
collapseBooleanAttributes: true,
removeCommentsFromCDATA: true,
removeOptionalTags: true
},
files: [{
expand: true,
cwd: '<%= mainApp.dist %>',
src: ['*.html', 'views/partials{,*/}*.html'],
dest: '<%= mainApp.dist %>/public'
}]
}
},
imagemin : {
dynamic: { // Another target
files: [{
expand: true, // Enable dynamic expansion
cwd: '<%= mainApp.dist %>/public/static', // Src matches are relative to this path
src: ['**/*.{png,jpg,gif}'], // Actual patterns to match
dest: '<%= mainApp.dist %>/public/static' // Destination path prefix
}]
}
},
});
// Used for delaying livereload until after server has restarted
grunt.registerTask('wait', function () {
grunt.log.ok('Waiting for server reload...');
var done = this.async();
setTimeout(function () {
grunt.log.writeln('Done waiting!');
done();
}, 1500);
});
grunt.registerTask('express-keepalive', 'Keep grunt running', function() {
this.async();
});
grunt.registerTask('serve', 'Compile then start a connect web server', function(){
grunt.task.run([
'clean:server',
'less:development',
'wiredep',
// 'concurrent:server',
//'connect:livereload',
'express:dev',
//'express-keepalive',
'wait',
'watch'
]);
});
grunt.registerTask('build', function(){
grunt.task.run([
'clean:dist',
'less:development',
'wiredep',
'useminPrepare',
'concurrent:dist',
'copy:styles',
'autoprefixer',
'concat',
'ngAnnotate',
'copy:dist',
'cdnify',
'cssmin',
'uglify',
'filerev',
'usemin',
'htmlmin',
'express:dev'
]);
});
grunt.registerTask('debug', [
'clean:dist',
'less:development',
'wiredep',
'copy:debug'
]);
grunt.registerTask('default', [
'serve'
]);
};
I found the solution to this by reverting to a previous git and manually adding changed.
Somehow it was an issue with node-scheduler. I was scheduling a task using a recurrence rule for dayOfWeek = 7. This was producing the error in grunt serve, nothing to do with the grunt file as it happens.
I changed this to dayOfWeek = 0 and it was fine.

Warning: Task "clean:server" not found

If I use any grunt task it throws this error. Someone on the irc channel said it was possible that my gruntfile was corrupt, but there is no information on the internet that could help me learn to fix this issue
Warning: Task "(some task)" not found. Use --force to continue.
Aborted due to warnings.
Execution Time (2014-07-22 18:06:52 UTC)
loading tasks 5ms ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 28%
serve 12ms ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 67%
Total 18ms
If I do grunt serve the error says that task "clean:server can be found".
but my gruntfile contains clean server
clean: {
dist: {
files: [{
dot: true,
src: [
'.tmp',
'<%= config.dist %>/*',
'!<%= config.dist %>/.git*'
]
}]
},
server: '.tmp'
}
Here is the entire gruntfile.js
// Generated on 2014-07-22 using generator-webapp 0.4.9
'use strict';
// # Globbing
// for performance reasons we're only matching one level down:
// 'test/spec/{,*/}*.js'
// use this if you want to recursively match all subfolders:
// 'test/spec/**/*.js'
module.exports = function (grunt) {
// Load grunt tasks automatically
require('load-grunt-tasks')(grunt);
// Time how long tasks take. Can help when optimizing build times
require('time-grunt')(grunt);
// Configurable paths
var config = {
app: 'app',
dist: 'dist'
};
// Define the configuration for all the tasks
grunt.initConfig({
// Project settings
config: config,
// Watches files for changes and runs tasks based on the changed files
watch: {
bower: {
files: ['bower.json'],
tasks: ['bowerInstall']
},
js: {
files: ['<%= config.app %>/scripts/{,*/}*.js'],
tasks: ['jshint'],
options: {
livereload: true
}
},
jstest: {
files: ['test/spec/{,*/}*.js'],
tasks: ['test:watch']
},
gruntfile: {
files: ['Gruntfile.js']
},
sass: {
files: ['<%= config.app %>/styles/{,*/}*.{scss,sass}'],
tasks: ['sass:server', 'autoprefixer']
},
styles: {
files: ['<%= config.app %>/styles/{,*/}*.css'],
tasks: ['newer:copy:styles', 'autoprefixer']
},
livereload: {
options: {
livereload: '<%= connect.options.livereload %>'
},
files: [
'<%= config.app %>/{,*/}*.html',
'.tmp/styles/{,*/}*.css',
'<%= config.app %>/images/{,*/}*'
]
}
},
// The actual grunt server settings
connect: {
options: {
port: 9000,
open: true,
livereload: 35729,
// Change this to '0.0.0.0' to access the server from outside
hostname: 'localhost'
},
livereload: {
options: {
middleware: function(connect) {
return [
connect.static('.tmp'),
connect().use('/bower_components', connect.static('./bower_components')),
connect.static(config.app)
];
}
}
},
test: {
options: {
open: false,
port: 9001,
middleware: function(connect) {
return [
connect.static('.tmp'),
connect.static('test'),
connect().use('/bower_components', connect.static('./bower_components')),
connect.static(config.app)
];
}
}
},
dist: {
options: {
base: '<%= config.dist %>',
livereload: false
}
}
},
// Empties folders to start fresh
clean: {
dist: {
files: [{
dot: true,
src: [
'.tmp',
'<%= config.dist %>/*',
'!<%= config.dist %>/.git*'
]
}]
},
server: '.tmp'
},
// Make sure code styles are up to par and there are no obvious mistakes
jshint: {
options: {
jshintrc: '.jshintrc',
reporter: require('jshint-stylish')
},
all: [
'Gruntfile.js',
'<%= config.app %>/scripts/{,*/}*.js',
'!<%= config.app %>/scripts/vendor/*',
'test/spec/{,*/}*.js'
]
},
// Mocha testing framework configuration options
mocha: {
all: {
options: {
run: true,
urls: ['http://<%= connect.test.options.hostname %>:<%= connect.test.options.port %>/index.html']
}
}
},
// Compiles Sass to CSS and generates necessary files if requested
sass: {
options: {
loadPath: [
'bower_components'
]
},
dist: {
files: [{
expand: true,
cwd: '<%= config.app %>/styles',
src: ['*.scss'],
dest: '.tmp/styles',
ext: '.css'
}]
},
server: {
files: [{
expand: true,
cwd: '<%= config.app %>/styles',
src: ['*.scss'],
dest: '.tmp/styles',
ext: '.css'
}]
}
},
// Add vendor prefixed styles
autoprefixer: {
options: {
browsers: ['last 1 version']
},
dist: {
files: [{
expand: true,
cwd: '.tmp/styles/',
src: '{,*/}*.css',
dest: '.tmp/styles/'
}]
}
},
// Automatically inject Bower components into the HTML file
bowerInstall: {
app: {
src: ['<%= config.app %>/index.html'],
exclude: ['bower_components/bootstrap-sass-official/vendor/assets/javascripts/bootstrap.js']
},
sass: {
src: ['<%= config.app %>/styles/{,*/}*.{scss,sass}']
}
},
// Renames files for browser caching purposes
rev: {
dist: {
files: {
src: [
'<%= config.dist %>/scripts/{,*/}*.js',
'<%= config.dist %>/styles/{,*/}*.css',
'<%= config.dist %>/images/{,*/}*.*',
'<%= config.dist %>/styles/fonts/{,*/}*.*',
'<%= config.dist %>/*.{ico,png}'
]
}
}
},
// Reads HTML for usemin blocks to enable smart builds that automatically
// concat, minify and revision files. Creates configurations in memory so
// additional tasks can operate on them
useminPrepare: {
options: {
dest: '<%= config.dist %>'
},
html: '<%= config.app %>/index.html'
},
// Performs rewrites based on rev and the useminPrepare configuration
usemin: {
options: {
assetsDirs: ['<%= config.dist %>', '<%= config.dist %>/images']
},
html: ['<%= config.dist %>/{,*/}*.html'],
css: ['<%= config.dist %>/styles/{,*/}*.css']
},
// The following *-min tasks produce minified files in the dist folder
imagemin: {
dist: {
files: [{
expand: true,
cwd: '<%= config.app %>/images',
src: '{,*/}*.{gif,jpeg,jpg,png}',
dest: '<%= config.dist %>/images'
}]
}
},
svgmin: {
dist: {
files: [{
expand: true,
cwd: '<%= config.app %>/images',
src: '{,*/}*.svg',
dest: '<%= config.dist %>/images'
}]
}
},
htmlmin: {
dist: {
options: {
collapseBooleanAttributes: true,
collapseWhitespace: true,
removeAttributeQuotes: true,
removeCommentsFromCDATA: true,
removeEmptyAttributes: true,
removeOptionalTags: true,
removeRedundantAttributes: true,
useShortDoctype: true
},
files: [{
expand: true,
cwd: '<%= config.dist %>',
src: '{,*/}*.html',
dest: '<%= config.dist %>'
}]
}
},
// By default, your `index.html`'s <!-- Usemin block --> will take care of
// minification. These next options are pre-configured if you do not wish
// to use the Usemin blocks.
// cssmin: {
// dist: {
// files: {
// '<%= config.dist %>/styles/main.css': [
// '.tmp/styles/{,*/}*.css',
// '<%= config.app %>/styles/{,*/}*.css'
// ]
// }
// }
// },
// uglify: {
// dist: {
// files: {
// '<%= config.dist %>/scripts/scripts.js': [
// '<%= config.dist %>/scripts/scripts.js'
// ]
// }
// }
// },
// concat: {
// dist: {}
// },
// Copies remaining files to places other tasks can use
copy: {
dist: {
files: [{
expand: true,
dot: true,
cwd: '<%= config.app %>',
dest: '<%= config.dist %>',
src: [
'*.{ico,png,txt}',
'.htaccess',
'images/{,*/}*.webp',
'{,*/}*.html',
'styles/fonts/{,*/}*.*'
]
}]
},
styles: {
expand: true,
dot: true,
cwd: '<%= config.app %>/styles',
dest: '.tmp/styles/',
src: '{,*/}*.css'
}
},
// Generates a custom Modernizr build that includes only the tests you
// reference in your app
modernizr: {
dist: {
devFile: 'bower_components/modernizr/modernizr.js',
outputFile: '<%= config.dist %>/scripts/vendor/modernizr.js',
files: {
src: [
'<%= config.dist %>/scripts/{,*/}*.js',
'<%= config.dist %>/styles/{,*/}*.css',
'!<%= config.dist %>/scripts/vendor/*'
]
},
uglify: true
}
},
// Run some tasks in parallel to speed up build process
concurrent: {
server: [
'copy:styles'
],
test: [
'copy:styles'
],
dist: [
'sass',
'copy:styles',
'imagemin',
'svgmin'
]
}
});
grunt.registerTask('serve', function (target) {
if (target === 'dist') {
return grunt.task.run(['build', 'connect:dist:keepalive']);
}
grunt.task.run([
'clean:server',
'concurrent:server',
'autoprefixer',
'connect:livereload',
'watch'
]);
});
grunt.registerTask('server', function (target) {
grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.');
grunt.task.run([target ? ('serve:' + target) : 'serve']);
});
grunt.registerTask('test', function (target) {
if (target !== 'watch') {
grunt.task.run([
'clean:server',
'concurrent:test',
'autoprefixer'
]);
}
grunt.task.run([
'connect:test',
'mocha'
]);
});
grunt.registerTask('build', [
'clean:dist',
'useminPrepare',
'concurrent:dist',
'autoprefixer',
'concat',
'cssmin',
'uglify',
'copy:dist',
'modernizr',
'rev',
'usemin',
'htmlmin'
]);
grunt.registerTask('default', [
'newer:jshint',
'test',
'build'
]);
};
May be you accidentally deleted some file in the node_modules/grunt-contrib-clean directory.
Delete this dir and repeat the npm install. I also detected the problem and this worked for me.

Resources