Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Heroku and EB deep links not routing #16

Closed
adamhpan opened this issue Nov 21, 2016 · 8 comments
Closed

Heroku and EB deep links not routing #16

adamhpan opened this issue Nov 21, 2016 · 8 comments

Comments

@adamhpan
Copy link
Contributor

I can't get the deep links to work when I'm hosting the application on Heroku/EB.
I've tried to run an nginx server to route everything to the index.html in ./dist but the deep links are still not found.

Can you run through how you hosted the project on Heroku?

@domfarolino
Copy link
Owner

There are technically two applications in this repository. One is for the backend which serves to static content or HTML, and the Angular portion of the app is only on the front-end. So I deployed the backend to Heroku (https://angular2-login-seed.herokuapp.com/api/....), and the front-end app is just in the gh-pages branch of this repository. When you visit https://domfarolino.com/angular2-login-seed you're hitting the static front-end angular app, and whenever the angular app needs some data to display on the page it hits the API deployed on Heroku. This make sense?

The front and back end are completely divorced, so the deep linking/routing is all done with the Angular app in the front-end.

@domfarolino
Copy link
Owner

It is possible to deploy them all with one app, but it is messier. You'd need the backend application to serve the same HTML file for any route that does not start with /api/ so that the Angular router could actually handle each route itself (and not let the backend serve some nonesense), and furthermore you'd need to be serving the index from the dist/ folder that contains the compiled version of the angular app.

When creating a robust single page app in something like Angular it makes sense to let Angular (with all its features and glory etc) handle just about everything except for dynamic data collection, which is what the backend does in this application. So when you deploy to Heroku you should only be deploying the back-end app, now you can serve the front-end from anywhere and just make sure the Angular app hits the correct back-end.

Let me know if you need any more info/help

@adamhpan
Copy link
Contributor Author

Totally, I get that we have the Angular app and api app.

I'm having trouble with the Angular app right now.
I can't seem to use any of the deep links when I only host it.
The app runs fine when it first get's hit but if I refresh, the page breaks.

@domfarolino
Copy link
Owner

Hmm, could you give me the URL you're hosting the Angular app at?

@adamhpan
Copy link
Contributor Author

Here we are
https://ng-login-seed.herokuapp.com/

Here are the reproduction steps

  1. pull the repo
  2. Change the following in package.json
    • Move angular-cli to dependencies so they're installed by heroku
    • Add the following pre and post install scripts as well as the http server start
      "scripts": {
      "start": "http-server ./dist",
      "preinstall": "npm install -g http-server",
      "postinstall": "ng build --prod"
      },
  3. Push to heroku for deployment
  4. Navigate to the heroku page
  5. Refresh

Expected - the login screen should display correctly
Actual - there's a white screen

I haven't enabled cors so none of the api calls will work.

@domfarolino
Copy link
Owner

Thanks for the information. http-server is a simple server in that it will serve you whatever files you're trying to get (denoted by URL). If it is anything like python -m SimpleHTTPServer it probably doesn't do much more than this (path aliasing and other things with logic). It is a dumb server, in that if a file exists it will give it to you. So if you visit /, the server will automatically look for a /index.html which exists since Angular built it. However this kind of server typically does not support deep-linking. Think about it, on the front end we've changed the URL from / => /login at some point, but we've never told the server about this. When the URL changed, Angular knew what to do and it changed the front-end content accordingly. The server however, only remembers our first request that it was able to handle successfully - /.

Fast forward to us refreshing the page after the URL changed on the front-end. Now we're actually saying, "hey server - serve us up the content at /login for us" since our URL has changed to /login. The server, http-server in this case will look for a /login folder in the ./dist folder in your case instead of serving up index.html. Since it can't find it, it will fail (different servers will fail differently). So the key to supporting deep-linking with a server is to serve the same static HTML index.html no matter what the route we request is. Why is this? Well because we've already seen that Angular knows how to deal with those links when they are given, we just need to make the server more like a sieve, so that it will always let Angular respond.

Regarding http-server, I've never used it so I don't know if there's a way to say "hey server, on request of /, /login, register, /heroes, ... serve the same index.html page no matter what". This is something you'll need to find out. With express/Node.js it is very very simple to do this.

Does this make sense why the deep-linking is failing? It is nothing to do with the Angular app, it is instead a fundamental issue that very watered-down basic http servers have when trying to serve single-page applications with routers built in. The idea is typically we want to serve the same static content no matter what request is made, and sometimes baking those rules into the server is simple.

@domfarolino
Copy link
Owner

domfarolino commented Nov 21, 2016

For example when I try to retrieve /login when running the http-server locally in the ./dist folder, I get the following error:

[Mon Nov 21 2016 17:02:24 GMT-0500 (EST)] "GET /login" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.100 Safari/537.36" [Mon Nov 21 2016 17:02:24 GMT-0500 (EST)] "GET /login" Error (404): "Not found"

Because we've got no rule telling the server to route everything to index.html. Regarding your original issue with the nginx server that should've routed everything to index.html I'm not sure why that did not work. I would assume the server was not set up to route everything to index.html as you may have thought but I could be wrong

@adamhpan
Copy link
Contributor Author

I'll try the nginx routing again.

Thanks for the help!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants