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
'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 :
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"
}