I am building a node.js app with express, I am hosting an Angular SPA in the public folder.
The app runs and the hosting works fine when I use the angular router for navigation around the website, but when I directly try to access the link, for example: http://192.168.1.4:3000/posts, the entire body of the website is just the JSON response object, without the app
this is the Node.js code handling the get request
postRouter.route('/')
.options(cors.corsWithOptions, (req, res) => {
res.sendStatus(200);
})
.get(cors.cors, (req, res, next) => {
posts.find({})
.then((post) => {
res.status(200);
res.setHeader('Content-Type', 'application/json')
res.send(post);
}, (err) => next(err))
.catch((err) => next(err));
})
this is my angular service sending out the get request
getPosts(): Observable<Post[]> {
return this.http.get(baseURL + 'posts')
.catch(error => { return this.processHttpService.handleError(error); });
}
Post Component .ts file
ngOnInit() {
this.postService.getPosts()
.subscribe(posts => { this.posts = posts, console.log(this.posts); },
errmess => this.errMess = <any>errmess);
}
Again, when i use my Angular 5 client app hosted in the public folder, built with ng build --prod
, the JSON object is retrieved from the mongodb database and is displayed correctly on my website, along with the rest of the app, the header, the body, and the footer.
it might also be worth noting that the console.log on the ngOnInit() is not displayed on the browser when using the direct link.
Any advice/fix is greatly appreciated
You have a clash of routes between angular and your express application. Angular is served up on one route (I'm guessing the /
route) and then it sort of "hijacks" the users navigation. It does this by not actually changing web pages, instead it just changes the URL in the navigation bar, but never actually makes a web request to get to that resource.
You've then got endpoints on a web server listening on those endpoints. This means the moment you visit the /posts
page, you're not asking angular to do anything. In fact, angular isn't even loaded because that only gets loaded on the /
route. Instead you're going straight to your API.
There are ways around this, to start with many people put their API fairly separately, either on a subdomain or mounted on /api
(such as /api/posts
). Then your angular app can be served up on the /
route. There are other techniques you can use to then allow a user to go to /posts
and still get your angular app loaded.
You can use a few approaches for this such as the hash location strategy, or you can serve up your angular application from any route on the application (*
in express) and load the angular app which will then take over. This second approach is most comment, it usually results in hosting your api on a sub domain and then serving your angular app on the *
route of the normal domain name. For example: api.myapp.com will serve only JSON responses, but any route on myapp.com will serve the angular app, such as myapp.com/posts.