Deploying Ionic2 on Heroku - node.js

I am trying to deploy my ionic2 app on Heroku. I looked at these sites:
http://blog.ionic.io/one-mean-ionic-2-todo-app-on-heroku-part-1/
https://www.joshmorony.com/building-a-review-app-with-ionic-2-mongodb-node/
https://devdactic.com/deploying-ionic-to-heroku/
and created a server.js file:
var express = require('express');
var app = express(); // create our app w/ express
var morgan = require('morgan'); // log requests to the console (express4)
var bodyParser = require('body-parser'); // pull information from HTML POST (express4)
var cors = require('cors');
app.use(morgan('dev')); // log every request to the console
app.use(bodyParser.urlencoded({'extended':'true'})); // parse application/x-www-form-urlencoded
app.use(bodyParser.json()); // parse application/json
app.use(bodyParser.json({ type: 'application/vnd.api+json' })); // parse application/vnd.api+json as json
// app.use(methodOverride());
app.use(cors());
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header('Access-Control-Allow-Methods', 'DELETE, PUT');
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
app.use(express.static('www'));
app.set('port', process.env.PORT || 5000);
app.listen(app.get('port'), function () {
console.log('Express server listening on port ' + app.get('port'));
});
Since I have no models and no DB at this time, I excluded mongo and mongoose.
The server runs fine when I run it on my local machine via npm start but when I run it on heroku, I get:
Cannot GET /
on the page. Heroku Logs shows:
2017-01-04T19:56:59.385666+00:00 heroku[web.1]: State changed from starting to up
2017-01-04T19:57:00.546815+00:00 heroku[router]: at=info method=GET path="/" host=hrmghp-companion.herokuapp.com request_id=4c010120-3dce-4f99-b31c-99dc0883f314 fwd="108.44.230.178" dyno=web.1 connect=1ms service=49ms status=404 bytes=364
2017-01-04T19:57:00.549928+00:00 app[web.1]: GET / 404 19.924 ms - 13
Am I missing something in my server.js file?
Edit:
I found the issue. I had www/ in my .gitignore file. I assumed that it would rebuild the app when deploying to heroku? Is this not how it works?

Don't add www to your repository. You don't want to keep track of all those files. Instead, include "postinstall": "ionic-app-scripts build" in the scripts section of your package.json. This will rebuild the app and regenerate the www folder for you on Heroku.

Just want to add something on to Alex's answer. Make sure you either add ionic-app-scripts as a dependency (as opposed to devDependency), OR disable production mode in heroku via heroku config:set NPM_CONFIG_PRODUCTION=false
So, adding "postinstall": "ionic-app-scripts build" in the scripts section of package.json, and disabling production mode worked for me.

Related

Connecting reactjs with nodejs

I have an app with front end react and backend node. The backend is tested with postman and working fine. the front end ui is tested with static data. Now I have set up a proxy with the react part to connect to the backend node.
My react app is runnning on port 3000
my node is running on port 5000.
When I request a route on my backend from my front end the app does not utilize the proxy set up Instead it gives me a Bad request error.
My front end is in client folder .Please help.
the project can be found on the following github link
https://github.com/prashantbhat84/mern-contactkeeper
Please help
It seems to be a cross-origin problem. There are two ways to solve cross-origin problems in node server,
Using cors node module
First install cors module. npm install cors
and then use it inside your app
const Express = require("express");
const BodyParser = require("body-parser");
const Cors = require("cors");
const app = Express();
app.use(Cors());
app.use(BodyParser.urlencoded({ extended: false }));
app.use(BodyParser.json());
app.listen(3001, 'localhost', (err) => {
if(err) {
console.log(err);
process.exit(-1);
}
console.log("Server listen port 8083");
});
simply use following headers
app.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
res.header("Access-Control-Allow-Methods", "GET, POST, OPTIONS, PUT, DELETE");
next();
});
NPM uses a configuration file and it can be added to via the command line npm config set. The key to getting it right is the spelling of the settings. This has bit me so many times now! Getting npm to work behind a proxy requires setting the proxy and https-proxy settings. The key is noticing the - (dash) is not an _ (underscore).
Open an command prompt or terminal session and run the following commands to configure npm to work with your web proxy. The commands use domain_name.com as the address and 8080 as the port.
npm config set proxy http://domain_name.com:8080
npm config set https-proxy http://domain_name.com:8080

Why is my server causing a syntax error when deployed to Heroku but runs with no errors locally (using Create React App, Node/Express)?

Edit to add picture of exact error, and to provide more info
When I click on main.35...js in the error message in the console, it shows me the source code to my index.html, all of it with the red underline, but I don't see the erroneous syntax there:
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"><meta name="theme-color" content="#000000"><link rel="manifest" href="/manifest.json"><link rel="shortcut icon" href="/favicon.ico"><link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous"><title>BoGoodSki.com</title><link href="/static/css/main.4d5a52c0.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script type="text/javascript" src="/static/js/main.35eb4822.js"></script></body></html>
Also, in development, there is no error or warning in VSCode regarding the index.html file. I'm confused for sure.
Thanks for the help so far!
End edit
I have an app deployed to Heroku that has been working well.
Today I made some changes to the Express server to handle a simple API post request to a MongoDB instance on mLab. I had to set up CORS policy as middleware but, otherwise, I didn't make any substantial changes to the server code.
My deployment flow has been to run 'npm run build' on the Create React App client, and then use the Heroku CLI to git push from my server folder. This process has worked well. Until today.
Now, when I deploy to Heroku, it says that it publishes successfully, but the app is blank in the browser and the console says that there is a syntax error of < in the build JS file. I can't currently reproduce the error because I rolled back to a working deployment in Heroku.
Here is my server code. Can you identify what may be causing the issue? My JS build files sit in client/build/static, just like Express expects them to, so I don't know what's up.
Appreciate the help.
index.js:
const express = require('express');
const mongoose = require('mongoose');
const keys = require('./config/config');
require('./models/FormData');
var bodyParser = require('body-parser');
mongoose.connect(keys.mongoURI);
const app = express();
const FormMessage = mongoose.model('formMessages')
app.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(bodyParser.json());
app.post("/submitMessage", (req, res) => {
var newMessage = new FormMessage(req.body);
newMessage.save()
.then(item => {
res.status(200).send();
})
.catch(err => {
res.status(400).send();
});
});
if (process.env.NODE_ENV === 'production') {
app.use(express.static('client/build'));
const path = require('path');
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'client', 'build', 'index.html'))
});
}
const PORT = process.env.PORT || 5000;
app.listen(PORT);
Fixed!!
Okay. Here are the steps that I took. I'm not sure which, individually, resolved the problem. But, altogether, they worked.
First, I deleted the existing main.35...js file in my source code direetory. Actually, I deleted the entire build/static folder. And then ran "npm run build" in the client directory to rebuild the React app.
I changed the node engine in my package.json from 8.1.1 to the version I am running locally, 9.2.1.
In my index.js, I removed the conditional regarding the production environment variable because, it occurred to me that it didn't make sense to serve it up differently locally than I would in production; I think that conditional was a remnant from something I had been working on earlier in the project.
Those steps taken together have done the trick. I appreciate all who have viewed this question and given it any thought. Thanks!

Integrating Angular with Nodejs

I tried to connect angular front end with nodejs earlier I ran ng build on public folder of app and then ran localhost:3000. No error was given on compilation but app is broken now. Now do I achieve it? My folder structure is like this
client
public
app.js
client contains all angular code, public contains compiled code of angular
till I have also changed output path to ../public in angular.json.
And here is my app.js:
var express = require('express');
var path= require('path');
var cors = require('cors');
var mongoose = require('mongoose');
var bodyParser = require('body-parser');
var passport = require('passport');
var app= express();
var port = 3000;
app.set('view engine','ejs');
//app.use(express.static(path.join(__dirname, 'public')));
app.set('views', path.join(__dirname, '/views'));
app.use(express.static(path.join(__dirname, 'public')));
app.use('/api', routesApi);
app.get('/', (req,res) => {
res.send("Invalid page");
});
app.listen(port, () => {
console.log(`Starting the server at port ${port}`);
});
I think up to now you have a build of a running angular application and perfectly running node.js server.
What you have to do is host your client application. Follow the following steps to get this working.
Install http-server globally on your machine using npm install http-server -g command
Then run http-server /path/to/your/dist/folder. (You should get a dist folder after running ng build --prod)
Then run your node.js server.
And open your browser and go to http://localhost:8080

Starting Express.js Using app.js or 'npm start'?

I've recently installed Node.js on a local server and when I create a 'server.js' file (adding a server using the .createServer() method), it loads fine.
However after installing Express.js, the default files are as follows:
/bin
/node_modules
/public
/routes
/views
app.js
package.json
After following some documentation, I am instructed to go to Terminal and enter the following command:
node app.js
To which nothing happens, the command line refreshes to the next line in less than a second, and opening a browser after visiting the proper IP and port, to no avail.
Below is the code inside of the app.js file:
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var routes = require('./routes/index');
var users = require('./routes/users');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/users', users);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
module.exports = app;
I understand that the actual 'express' module that is being required in the beginning of the file is where the magic happens, however, when I run the command line:
node app.js
Nothing happens. However, if I call the following line:
npm start
Everything appears to be okay. I would like to follow the documentation as is, any reason why the app.js wouldn't be working?
Thank you.
UPDATE: My question was too similar to another one already posted, so I must clarify exactly how they were different. In the other question, a person was questioning a code number they received while running the Supervisor command on the default 'app.js' file.
While similar in nature, this question should remain, as those who are confused by using my same approach will focus on the identity of the actual 'app.js' file by using 'node app.js' without having full knowledge of the Supervisor utility.
Regards.
Thank you all for your great responses, as they really allowed me to understand what is actually going on with the app.js file and where it receives it's functionality. Thank you to both Matthew Bakaitis and Bjarni Leifsson for their great input.
The only reason why I am going to go ahead and answer my own question is because while the nature of the app.js file was explained, exactly how to replicate calling the 'node app.js' command from the command line as to replicate a Node.js book that I was following wasn't implicitly addressed.
After searching google with the specific phrase "app.js in previous express.js versions", I happened upon a great article by Jilles Soeters entitled "Understanding the Express app.js":
http://jilles.me/getting-the-express-app-js/
Below is the excerpt of the solution that worked for me:
The file I'm covering is app.js, the main configuration file for your
Express app. When I first opened app.js it confused me. I will save
you the trouble of doing research and just cover them here.
Before you do anything add the following to your app.js
app.listen(3000);
You need that in order to be able to actual open your app in the
browser. Go to 127.0.0.1:3000 after you've started your app (using
node app.js)
After doing this, I was able to run the command
node app.js
I was able to run this command from the root directory of the Express install and proceed with my Node.js book with no additional problems.
This is a common problem that is caused when tutorials don't clearly explain what express is doing when it generates an app. You're trying to learn the new tech, but the tutorial is actively working against you. :(
The answer:
When you use the generator, package.json is configured so that npm start calls ./bin/www.
That file includes app.js and after the include, calls app.listen.
app.js doesn't call app.listen which is why if you call it directly, it exits with no code or info. You've got to call ./bin/www or you have to modify app.js...which then defeats some of the reasons you'd use a generator.
A related question here on the site saw a similar problem when trying to use supervisor to keep an app running but kept getting an exit 0 result.
How I understand this, and I have just started to use node.
There is a bin folder with www in it. There all the magic happens. So when you do node app.js it gets executed but the logic to the everything is in bin/www
So if you look into package.json you see this init :
"scripts": {
"start": "node ./bin/www"
},
So giving that, you see to execute the script you use the start method and it is linked to ./bin/www
If you take a look in that file you will find out that the whole logic of the server to start up is in there.
So if you change start to something else, like TurnOn and would do npm TurnOn, it will execute ./bin/www and the whole project for you.
The structor of the project is all linked together, and app.js is not enough to start the server.
Hope this helps.
When using Express the Express instance will create the server for you. Typically your app/index/server.js file will begin with these lines:
const express = require('express');
const app = express();
These lines require Express and then instantiate an instance of Express within the app variable. Express then uses var server = http.createServer(app); to start a server for you. All you need to do is to make sure your app listens to that server (as you wrote). However, the port for the connection may vary so it is not advisable to hard-code it. Instead it should be retrieved from the app variable as such:
app.listen(app.get('port'), function(){
//Something to do when the server starts.
});
Additionally, after creating your own app.js file make sure to change your package.json file to start the app via app.js instead of the Express module. By default your package.json might look like this:
"scripts": {
"start": "node ./bin/www"
},
But after you created your own app/index/server.js file you want node to start running that file on startup instead:
"scripts": {
"start": "node app.js"
}
You can then start your app by writing npm start from the project directory.

Hosting a nodejs express site on Windows Azure

I created a new NodeJS site based on the documentation of Durandal. It works locally. I set up Windows Azure to pull in the changes of my GitHub repository, which it does correctly.
However, (after enabling errors) I'm getting the an internal server error.
I checked my FTP for the logs, but don't have any. There is a 'Git' folder, but nothing interesting there.
When I change my server.js file to the hello world sample, everything works:
var http = require('http')
var port = process.env.PORT || 1337;
http.createServer(function(req, res) {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello World\n');
}).listen(port);
This is my server.js now:
var express = require('express'),
routes = require('./routes'),
engines = require('consolidate');
exports.startServer = function(config, callback) {
var port = process.env.PORT || config.server.port || 1337;
var app = express();
var server = app.listen(port, function() {
console.log("Express server listening on port %d in %s mode", server.address().port, app.settings.env);
});
app.configure(function() {
app.set('port', port);
app.set('views', config.server.views.path);
app.engine(config.server.views.extension, engines[config.server.views.compileWith]);
app.set('view engine', config.server.views.extension);
app.use(express.favicon());
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.compress());
app.use(config.server.base, app.router);
app.use(express.static(config.watch.compiledDir));
});
app.configure('development', function() {
app.use(express.errorHandler());
});
app.get('/', routes.index(config));
callback(server);
};
So, has anyone succesfully hosted an Express (or more specifically, the Durandal skeleton for Mimosa) NodeJS site on Windows Azure? Or do you know how or where I can find the internal server error?
I've launched a few express applications on the Windows Azure platform and found that I had several instances of it failing quite silently. I personally have found the approach suggested in this post by Jay Harris really helpful as it allows me to import dependencies (npm, bower or other) and run grunt tasks to compile the project etc.
A few things worth noting is that often after a new deploy the updates did not display until restarting the Azure server in the control panel. Sometimes the deploy scripts timed out and I had to check them regularly.
This doesn't exactly answer what's wrong with your code (sorry) but I've posted an example using the method mentioned above that may help. The main deploy files are 'web.config', 'deploy.sh' and '.deployment' as well as your 'package.json' file.

Resources