How to deploy a reveal.js app to heroku? - node.js

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!

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/

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.

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"
},
...

Related

Deploying first app to Heroku: Error R10 (Boot timeout) -> Web process failed to bind to $PORT within 60 seconds of launch

I am trying to deploy an Express/React/Mongo app to Heroku for the first time.
It is failing with a 503 error. The logs states the following:
Error R10 (Boot timeout) -> Web process failed to bind to $PORT within
60 seconds of launch
I have set the following port variable in the root index.js file:
const port = process.env.PORT || 3000;
and use it here:
app.listen(port, function(){
console.log("Express server is running on port " + port)
})
It outputs "Express server is running on port 3000", which suggest that it is not picking up the Environmental variable.
I have been trying to follow instructions here: https://coursework.vschool.io/deploying-mern-with-heroku/
The key part that I am may be misunderstanding:
With Heroku, you need to set the environment variables on your newly
created Heroku app so it knows which values to use when the project is
deployed. You can do this two ways, either online on Heroku's website,
or through the command line using the heroku CLI. Since we are not
creating a new Heroku remote repository, all environment variables
will need to be added using Heroku.com.
I took this to mean that I should set an environmental variable Heroku.com, which I believe I have done so:
What am I failing to grok?
EDIT: I have tried setting theprocess.env.PORT=8000 from the Heroku CLI:
heroku config:set process.env.PORT=8000
But get the following error:
» Error: Missing required flag: » -a, --app APP app to run
command against » See more help with --help
Here is the full index.js:
const express = require('express'),
cors = require('cors'),
app = express(),
port = process.env.PORT || 3000;
bodyParser = require('body-parser'),
todoRoutes = require('./routes/todo'),
path = require("path");
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use(cors());
app.use(express.static(path.join(__dirname, "client", "build")))
app.get('/', function (req, res){
res.send('Root route')
})
app.use('/api/todos', todoRoutes);
app.get("*", (req, res) => {
res.sendFile(path.join(__dirname, "client", "build", "index.html"));
});
app.listen(port, function(){
console.log("Express server is running on port " + port)
})
I had local dev server running whilst deploying to Heroku. Tried redeploying after stopping dev server, and it worked. Local servers interfered with environment variables in deployment.

express server starting react client

Until now, I have been using create-react-app for my projects, with the express-server and the react client each in their own folders.
However, I am now trying to avoid create-react-app in order to really understand how everything work under the hood. I am reading an Hacker Noon article that explains how to setup react with typescript and webpack. In this article they also have the express server at the root of the client which compiles everything itself:
const path = require('path'),
express = require('express'),
webpack = require('webpack'),
webpackConfig = require('./webpack.config.js'),
app = express(),
port = process.env.PORT || 3000;
app.listen(port, () => { console.log(`App is listening on port ${port}`) });
app.get('/', (req, res) => {
res.sendFile(path.resolve(__dirname, 'dist', 'index.html'));
});
let compiler = webpack(webpackConfig);
app.use(require('webpack-dev-middleware')(compiler, {
noInfo: true, publicPath: webpackConfig.output.publicPath, stats: { colors: true }
}));
app.use(require('webpack-hot-middleware')(compiler));
app.use(express.static(path.resolve(__dirname, 'dist')));
In the end, the start command looks like it:
"start": "npm run build && node server.js"
So I assume the client and the server start on the same port.
Why would you do such a thing? Are there any pros and cons?
It is true that this will allow your development to happen using the same server as express and that web pack will continuously update your dist/index.html file with whatever updates you make to your file. There's not too much of a disadvantage to this as this is just for development. But typically on prod you'll have a single built file that you will serve. And it will not web pack-dev-middleware to be running. Once you've built your server. For the purposes of production it might be possible that you'll only need static assets. But typically, even the server which serves mostly client files will potentially need a server if you want to do server side rendering and/or code splitting.
The command: "npm run build && node server.js" will run the bash/cmd commands into the terminal. npm run build is one step because of the use of && it will if that command succeeds, run the next command which is node server.js which is a strange command I would probably run node ./ (and put the server as index.js) or at least just write node server.
What I'd prefer to see in your package.json:
"start": "yarn build && node ./"
That would be possible if you mv server.js index.js (and npm i -g yarn).
Another thing to note, and look into is what the build step does.
Further Explanation:
The command runs the build step so check what your "build": key runs in your package.json.
This command will probably not exit with the code 1 (any exit code of a terminal process that is above 0 will result in an error and will not pass the &&).
Presumably, the build process described in the package.json will take all the javascript and CSS files and put them into the index.html file which will then be sent to the client side whenever someone access the '/' path.
After that succeeds, it will start the server that you put the code to above.
res.sendFile(path.resolve(__dirname, 'dist', 'index.html'));
will happen if anybody comes across the '/' path.

Error deploy heroku nodejs app

When i deploy application, i get error - Error: EROFS: read-only file system, open '/access.log' at Error (native)
what is happend?
index.js:
var app = require('./src/app');
app.set('port', (process.env.PORT || 5000));
enter code here
app.listen(app.get('port'), function() {
console.log('Node app is running on port', app.get('port'));
});
If you are using yarn, one of the most recent versions (1.0.0rc?) is causing this problem. If you set the yarn version explicity in your package.json engines config to an earlier version, like 0.27.5, that should solve your problem. i.e:
"engines": {
"node": "8.2.1",
"yarn": "0.27.5"
},
At least this fixed the issue for me.

Port Timeout With NodeJS/Webpack Heroku Deployment

Note: Everything works perfectly on my localhost environment. When I git push heroku master I get a successful push/deploy. I check the Heroku Logs and I see this error:
[]: Stopping process with SIGKILL
[]: Error R10 (Boot timeout) -> Web process failed to bind to $PORT within 120 seconds of launch
I have read many posts regarding this issue and the fix that I see is
app.set('port', (process.env.PORT || 4000));
This is not my fix since I am already doing this in my server code. Here is my server code:
var path = require('path');
var express = require('express');
var app = express();
app.set('port', (process.env.PORT || 4000));
app.use(express.static(__dirname + '/public'));
app.get('*', function response(req, res) {
res.render(path.join(__dirname, 'public/index.html'));
});
app.listen(app.get('port'), 'localhost', function onStart(err) {
if (err) {
console.log(err);
}
console.info('==> Listening on port %s.', app.get('port'));
});
NOTE: In the Heroku logs, ==> Listening on port %s. is printed and THEN the timeout happens after that (with no error). So it does get to the end of my server code without error and it prints the correct, random Heroku port.
Furthermore, webpack -p also creates my bundle.js correctly too.
My package.json has these two commands and they are executed without error:
"start": "NODE_ENV=production webpack -p && node server",
"postinstall": "bower install --force"
I am truly at a loss. Please help!
EDIT: I believe I have truly isolated the problem to my server.js file. I ended up doing webpack -p and pushed up the bundle.js file––essentially bypassing webpack on Heroku. I then do the simple npm start command (which is essentially just node server.js command) and my app still times out when trying to connect to the port.
WOW I figured it out. I had this line in my server:
app.listen(app.get('port'), 'localhost', function onStart(err) ....
I just needed to remove 'localhost' from the listen() function.

How do I make Openshift to use Express 4, instead of its installed Express 3?

I developed my Nodejs Express app locally using Express 4 and it works as expected on my computer. I then git the whole app up to Openshift. When I try to run it Openshift returns"503 Service Unavailable". If I ssh into my base Node cartridge and do "express -V" it returns version 3.2.5. I get the same version 3.2.5 if I go into my app folder at app-root/repo and run "express -V".
So clearly my Express 4 which was included in the git upload in my app's node_modules is not being used. What is the solution to use Express 4 as required by my app?
Ideas are- remove Openshift's version of Express 3, force Openshift to use my Express 4 in my app area, upgrade Openshift's Express 3 to Express 4. I cannot figure out how to do any of those and I have researched this.
Here's how to troubleshoot:
ssh into your cartridge
cd into the app-root/repo directory
run grep version ./node_modules/express/package.json
you should see a version based on your package.json dependency
verify your package.json has a scripts section containing a start command that just runs your app with something like node ./server.js (server.js being whatever file you coded your main app start script in). You don't need the express command line program to launch an express server. It's for setting up new project boilerplate and other ancillary tasks.
To see the version of express running within your app, you can add this code to your server.js (or equivalent) file: console.log(require("express/package").version);
Look at this project to know how to integrate openshift with express4
Its a simple example .
https://github.com/master-atul/openshift-express4
try this
rhc ssh
cd app-root/repo
npm start
also edit the ./bin/www
var port = normalizePort(process.env.OPENSHIFT_NODEJS_PORT || '8080');
var ip = process.env.OPENSHIFT_NODEJS_IP;
if (typeof ip === "undefined") {
// Log errors on OpenShift but continue w/ 127.0.0.1 - this
// allows us to run/test the app locally.
console.warn('No OPENSHIFT_NODEJS_IP var, using 127.0.0.1');
ip = "127.0.0.1";
};
//app.set('ip', port);
app.set('port', port);
var server = http.createServer(app);
server.listen(port, ip);
server.on('error', onError);
server.on('listening', onListening);
you can follow step:
copy all content bin/www and replace all content in file server.js:
Change some content at server.js:
from
`var port = normalizePort(process.env.PORT || '3000');`
to
var port = normalizePort(process.env.OPENSHIFT_NODEJS_PORT || '3000');
Add line:
var ip = process.env.OPENSHIFT_NODEJS_IP || '127.0.0.1';
from
server.listen(port);
to
server.listen(port, ip);
Add more to package.json
from
"scripts": {
"start": "node bin/www"
},
to
"scripts": {
"start": "node server.js"
},
Add line:
"main": "server.js",
Use npm install --save module-name for npm install
create file .gitignore with content:
node_modules
on local run node server.js to start server with address localhost:3000
upload to openshift:
git add .
git commit -m "First update new server version"
git push
Browser: domain-appname.rhcloud.com

Resources