Heroku Node/React Deployment Routes Everything to index.html - node.js

I have an app.js node main file where I define my api path as the following
app.get('/api/users', UserController.get);
Below in the same file I have the following
app.use(express.static(path.resolve(__dirname, "./front/build")));
app.get("*", function (request, response) {
response.sendFile(path.resolve(__dirname, "./front/build", "index.html"));
});
The index.html successfully serves React App.
If I open my heroku app somewhere at my-app.herokuapp.com it will open the React app which is intended but the Problem is my-app.herokuapp.com/api/users also serves index.html file instead of JSON that the endpoint is supposed to return.
I tried
I replaced endpoint route definition to come before the "" definition (didn't suffice)
EVEN more, I removed redirection to index.html but heroku still opens the index.html page with any type of request (the "" redirection still works). So, it might have cached something?
Is it about cache (how to clean?) or any other suggestions?

You should create routes and work in a proper flow for each functionality,
For Example:
//app.js
app.use("/api/user",userRoutes);
//UserRoutes
router.post("/signup",UserController.signup);
//UserController
exports.signup = async (req,res,next) => {
//Signup function to add a new user when the user provides required info
}
In this way, you code will be easily accessible and much efficient

Related

How to enable URL routing in Node and Elm application (Heroku)?

I have an elm application running on Heroku.
I didn't want to use a third party elm buildpack, so I compiled the elm files locally and pushed elm.js onto the Heroku server.
My application is using Node.js backend so I'm using this code in expresss to
serve index.html:
if(process.env.NODE_ENV === 'production') {
app.use(express.static('client'));
app.get('*', (res:any) => {
res.sendFile(path.resolve(__dirname, 'client', 'index.html'));
});
}
I can go to the heroku URL and everything works perfectly. If I click on the internal /login link, I'm redirected to the login page and my url changes to ww.mywebsite.com/login. Internal routing is not my problem.
This is my problem: Although internal routing works, if I were to manually write www.mywebsite.com/login in the navigation bar, instead of seeing the login page, I see Internal Server Error
How do I fix this? Would I need a heroku buildback to accomplish this?
As #kaskelotti from the comments pointed out, Internal Server Error was printing because the files were being found, but another error was happening once they were found. If the files had not been found I would have received a 404 error.
This was a syntax error in my express code that matched all requests with my static index.html file.
The code posted in my question is wrong, THIS is how it should look:
if(process.env.NODE_ENV === 'production') {
app.use(express.static('client'));
app.get('*', (req , res) => {
res.sendFile(path.resolve(__dirname, 'client', 'index.html'));
});
}
The difference is the argument to the callback function in app.get. Originally it was (res) instead of (req, res), so the res variable was mistaken for an object of type Request and not Response, since it was the first argument.
Also as #kaskelotti pointed out, Heroku is irrelevant to this problem.

How to create a node based server to serve REST API and also deploy the application.

I am new to nodeJS server area, need help in understanding how to work with REST API (using express) and deploy the angular application over a singe node server and same ports.
By deploying i want to understand if user hit below url http://localhost:8000/<page_name> then the specified page should open.
And is user hit below url using get or post request
http://localhost:8000/api/<api_name> then a json or a text will be returned.
How to run both the thing over a single node server.
Lets assume, you have all your static files in the /public folder of you app. Generally spoken, if you are using express.static, you should also get your index.html because this is handled by default for each directory.
In your case, as you are using Angular, the routing is handled from the client side (SPA). You should only have one single index.html after building your Angular app. All files from your dist folder should then be placed into your /public folder. Then you need to make sure, that initial file serving provides your index.html like so:
In this example static files are served first, then your API and if nothing is found, you are getting back you index file.
const express = require('express');
const app = express();
// serve static files
app.static(__dirname + '/public'));
// serve your API
app.get('/api/welcome', function (req, res) {
res.send('Welcome');
});
// fallback routing (server side handling)
app.get(/.*/, function (req, res) {
res.sendFile(__dirname + ‘/public/index.html‘
});
app.listen(3000);
Next time please make sure, to give all necessary information in your question ;-)
With the help from Sebastian, so far I can find a solution but its not working when i am hitting URL for different pages.
const express = require('express');
const app = express();
app.use(express.static('public'))
Please provide your suggestions.

Angularjs4 with express generator

Just developed a simple angular 4 application with this tutorial
https://scotch.io/tutorials/mean-app-with-angular-2-and-the-angular-cli
But how can i integrate angular 4 app to a express application that generated with express generator??.
One approach is REST API's method that is express JS app use as API provider and the angular application communicate with REST api.
But i would like to serve the angular application from express application itself..
I think this will helpful to you. First I assume, you use express server to handle some api request and let's say those routes are begin with /api. they can be differ from yours.
First build your angular application by ng build and it will create a folder called /dist in your project folder.
Copy that folder in to your express project /public folder. You have to put them in an static routed folder. /public folder is a default static route folder. That is why I put it there. If you have your own one, you can put there too.
edit your app.js file as follows
// Set our api routes
app.use('/api', api); // API router definitions.
// Catch all other routes and return the index file
app.get('*', function(req, res) {
res.sendFile(path.join(__dirname, 'dist/index.html'));
});
Hope you will help this way. Thanks.
You can serve it through your server like this:
// Catch root route and return index.html
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, 'app/index.html'));
});
// Catch all other routes
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'app', req.originalUrl));
});
But be careful to set the right path to your index.html.
There is a technology stack called MEAN which means (coincidence :) MongoDB, Express, Angular and Nodejs. So this is basically what you are looking for.
Altough you can create you own file structure, there is a mean-cli similar to Express-generator and the angular-cli. You can find it here.
In order for Angular to work properly (like requesting a site like example.com/something and then also activate the route something) I always return my index.html for any request and setup express to return all static files as well. Then I create a route /api which handles all my REST api requests.
Make sure to first setup your /api route, then your other static files from angular like bundle.js and finally index.html as route **.

Node React structure without view engine

I'm new to node. I was using express-handlebars as my view-engine, but now I've added React and I understood that I no longer require handlebars. The problem that I'm having is that in order to get to the index.html page, without handlebars, I had to use
app.use(express.static('./public'));
Everything gets rendered from react, but what if I want to do some other things when the user goes to the index page like
app.get("/",function(req,res){
console.log("connected");
});
If I add the get request after exporting the static files, the console.log never gets called. If I use it before, it does get called, but I can see the page loading forever. How should I structure the application now that I'm using react and I don t have a view engine anymore?
In your specific case, if you don't want to render anything to the user, you should turn your function into a middleware :
app.get("/",function(req,res, next){
console.log("connected");
next();
});
and put it before the app.use(express.static('./public'));
However, if you want to do actual logic with return values and such, I would suggest that you setup some kind of API that you request using Ajax from the client.
You can check my repository
https://github.com/kennethmervin01/react-node-production
it's a boilerplate to serve react app in node.js/express
then check my code inside app.js
You just need to copy the production build of your react app inside the react folder
app.use(express.static(path.join(__dirname, "../react")));
app.get("/*", (req, res) => {
res.sendFile(path.join(__dirname, "../react", "index.html"));
});

How to use AngularJS routes with Express (Node.js) when a new page is requested?

I'm using Express, which loads AngularJS from a static directory. Normally, I will request http://localhost/, in which Express serves me my index.html and all of the correct Angular files, etc. In my Angular app, I have these routes setup, which replace the content in an ng-view:
$routeProvider.when('/', {
templateUrl: '/partials/main.html',
controller: MainCtrl,
});
$routeProvider.when('/project/:projectId', {
templateUrl: '/partials/project.html',
controller: ProjectCtrl,
});
$locationProvider.html5Mode(true);
On my main page, I have a link to <a href="/project/{{project.id}}">, which will successfully load the template and direct me to http://localhost/project/3 or whatever ID I have specified. The problem is when I try to direct my browser to http://localhost/project/3 or refresh the page, the request is going to the Express/Node server, which returns Cannot GET /project/3.
How do I setup my Express routes to accommodate for this? I'm guessing it will require the use of $location in Angular (although I'd prefer to avoid the ugly ?searches and #hashes they use), but I'm clueless about how to go about setting up the Express routes to handle this.
Thanks.
with express 4, you probably want to catch all requests and redirect to angularjs index.html page.
app.use(app.router); doesn't exist anymore and res.sendfile is deprecated, use res.sendFilewith an uppercase F.
app.post('/projects/', projectController.createProject);
app.get('/projects/:id', projectController.getProject);
app.get('*', function (req, res) {
res.sendFile('/public/index.html');
});
put all your API routes before the route for every path app.get('*', function (req, res){...})
I would create a catch-all handler that runs after your regular routes that sends the necessary data.
app = express();
// your normal configuration like `app.use(express.bodyParser());` here
// ...
app.use(app.router);
app.use(function(req, res) {
// Use res.sendfile, as it streams instead of reading the file into memory.
res.sendfile(__dirname + '/public/index.html');
});
app.router is the middleware that runs all of your Express routes (like app.get and app.post); normally, Express puts this at the very end of the middleware chain automatically, but you can also add it to the chain explicitly, like we did here.
Then, if the URL isn't handled by app.router, the last middleware will send the Angular HTML view down to the client. This will happen for any URL that isn't handled by the other middleware, so your Angular app will have to handle invalid routes correctly.
I guess I should have clarified that I wasn't interested in using a template engine, but having Angular pull all of the HTML partials on it's own, Node is functioning completely as a static server here (but it won't be for the JSON API. Brian Ford shows how to do it using Jade here: http://briantford.com/blog/angular-express.html
My app is a single-page app, so I created an Express route for each possible URL pattern, and each of them does the same thing.
fs.readFile(__dirname + '/public/index.html', 'utf8', function(err, content) {
res.send(content);
});
I was assuming I would have to pass some request variables to Angular, but it looks like Angular takes care of it automatically.

Resources