4

I am trying to deploy a reveal.js application to Heroku. Reveal.js runs on node via grunt connect command. The app also requires ruby for compiling assets on-the-fly. Locally, I can run the app by using grunt serve.

Initially, because of compass being a dependency of grunt watch, Heroku only detected the Gemfile and assumed I was running a ruby app. I used the nodejs custom buildpack to force Heroku to see it as a nodejs app.

Procfile contains

web: grunt serve

Log shows

 2013-06-17T13:51:56.187012+00:00 heroku[router]: at=error code=H14 desc="No web processes running"

heroku ps shows nothing either. I can run "heroku run grunt serve" successfully, and I have modified the default Gruntfile.js that comes with reveal to accept process.env i.e.

connect: {
  server: {
    options: {
      port: process.env.PORT || 8000,
      base: '.'
    } 
  }
}

As a last attempt, I tried using the Heroku-nodejs-grunt build pack (https://github.com/mbuchetics/heroku-buildpack-nodejs-grunt) which will run a grunt task on deploy to compile assets. Still no luck, heroku logs --tail still shows no process running. Exploring with heroku run reveals that grunt is available, and the grunt serve command successfully executes.

When starting to use the new grunt build pack I got an error with the above Gruntfile.js saying "process" is undefined. I switched the port to 0.

The port on which the webserver will respond. The task will fail if the specified port is already in use. You can use the special values 0 or '?' to use a system-assigned port.

Didn't work, tried "?", didn't work (still no web process and heroku restart doesn't do anything)

I can't figure out how to get Heroku to use grunt serve as my main web server process!

sschale
  • 5,168
  • 3
  • 29
  • 36
Tommy Devol
  • 155
  • 1
  • 6

3 Answers3

6

I was able to make it work using nodejs and expressJs.

By following the heroku "getting started with nodejs", I was able to get a working webapp with expressjs and by declaring this in the web.js:

var express = require("express");
var app = express();
app.use(express.logger());
app.use("/", express.static(__dirname));

var port = process.env.PORT || 5000;
app.listen(port, function() {
  console.log("Listening on " + port);
});

With this you serve everything from / statically.

You have the sources here: https://github.com/MichaelBitard/revealjs_heroku and a working example here: http://murmuring-cove-4212.herokuapp.com/

michael_bitard
  • 3,613
  • 1
  • 24
  • 35
  • This works great and is detailed in a sitepoint post as well. If you follow Michael's note, just ensure that you have added Express as a dependency in your package.json. http://www.sitepoint.com/creating-slick-html-presentations-using-reveal-js/ – AndyBean Jun 23 '14 at 16:54
0

Your problem was that by default grunt serve binds to localhost. For it to work you will need to do a couple of small changes to reveal.js:

First add grunt-cli as a devDependency:

diff --git a/package.json b/package.json
index 10489bb..4c58442 100644
--- a/package.json
+++ b/package.json
@@ -36,6 +36,7 @@
     "grunt-contrib-connect": "~0.8.0",
     "grunt-autoprefixer": "~1.0.1",
     "grunt-zip": "~0.7.0",
+    "grunt-cli": "~0.1.13",
     "grunt": "~0.4.0",
     "node-sass": "~0.9.3"
   },

Then add a hostname parameter to grunt that will be used to bind to 0.0.0.0 instead of localhost.

diff --git a/Gruntfile.js b/Gruntfile.js
index 3e67b9f..b2bfc47 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -1,5 +1,6 @@
 /* global module:false */
 module.exports = function(grunt) {
+   var hostname = grunt.option('hostname') || 'localhost';
    var port = grunt.option('port') || 8000;
    // Project configuration
    grunt.initConfig({
@@ -94,6 +95,7 @@ module.exports = function(grunt) {
        connect: {
            server: {
                options: {
+                   hostname: hostname,
                    port: port,
                    base: '.',
                    livereload: true,

Now you can create a Procfile with the following contents to deploy to Heroku:

web: npm install && node_modules/.bin/grunt serve --hostname 0.0.0.0 --port $PORT

I have created a PR for the needed changes to reveal.js.

dvim
  • 2,223
  • 1
  • 17
  • 17
0

Currently with express v~4.13.3 express.logger() is deprecated and is not included with the express package. To solve this I had to import the dependency morgan.

My web.js file ended up being the following:

var express = require('express');
var morgan = require('morgan');
var app = express();
var port = process.env.PORT || 5000;

app.use(morgan('combined'));
app.use('/', express.static(__dirname));
app.listen(port, function() {
  console.log('Server started on ' + port);
});

As well, I needed to update my package.json to include the morgan lib. My dependencies in the file works with:

...
"dependencies": {
    "express": "~4.13.3",
    "morgan": "~1.7.0",
    "grunt-cli": "~0.1.13",
    "mustache": "~2.2.1",
    "socket.io": "~1.3.7"
},
...
jshaw3
  • 331
  • 2
  • 15