5
votes

I have an angular project which has multiple routes say /category/fruit/apple so the full url is http://myserver/category/fruit/apple through router link everything is fine but if I open this link directly in typing in URL then it is 404 my backend is nodejs with express. And the 404 make sense as there is no route configured like this.

My Question, In this kind of situation how should I handle?

I thought I had, redirect to root http://myserver?path=category-fruit-apple and from the root component do the dynamic routing. Is it the correct way ?

Please suggest the best way.

7
Do you have nginx before node.js or not? - Sergey Mell
what server do you use to host the angular application , is it a Apache server ?. here is an article to tackle the same issue if you are on apache : joeljoseph.net/… - Joel Joseph
What server are you using? - r2018

7 Answers

3
votes

There is a frontend-only solution (so, zero configuration server-side), too, namely hash routing. Add a line

useHash: true

in the root router module's configuration (then, the urls will look something like http://myserver/#/category/fruit/apple).

3
votes

Because it´s just javascript, the server didn´t know the route.
You have to add these lines in .htaccess

RewriteEngine On
# If an existing asset or directory is requested go to it as it is
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^ - [L]

# If the requested resource doesn't exist, use index.html
RewriteRule ^ /index.html

So, if the server didn´t find this route, you redirect to your angular-root and angular can handle this route. Therefore you can also replace "index.html" with the route, where your angular-root is.

1
votes

Of course you need to config your server to route to the right content.

Two examples are apache http server or nginx.

Here are some minimal config examples for both.

Angular apache example (.htaccess):

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteBase /
  RewriteRule ^index\.html$ - [L]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule . index.html [L]
</IfModule>

Nginx example (nginx.conf):

server {
    listen 80;

    server_name your.app;

    location / {
        proxy_pass       http://localhost:4200;
        proxy_set_header Upgrade    $http_upgrade;
        proxy_set_header Connection $http_connection;
        proxy_set_header Host       $host;
    }
}
0
votes

You can apply simple redirects to the index.html for everything that isn't a resource. I've got a public repo you might find useful, it's an incredibly simple express server I use to test the hosting of various Angular apps:

https://github.com/hevans90/node-ng-server/blob/master/server.js

tl;dr: make a list of resource file types & their directory, to serve your assets, but otherwise redirect ALL requests to index.html & let the Angular router do its work.

0
votes

As other people wrote, it's just a matter of redirect to index.html instead of throwing 404 on the server side.

There's a whole section that talks exactly about this on Angular's webpage.

0
votes

Its because your server does not know the route. The server understands only one route i.e. index.html

When the index page is loaded, client side rendering comes into picture. Angular determines the component to be loaded at client side and loads appropriate component.

When you navigate using links in the page, track your network calls, you will see that no request goes to backend. When you reload the route, then this entire route goes to server and it throws 404.

You can use HashLocationStrategy. This would append # in your route #/category/fruit/apple

All servers will ignore the route after # loading the main page, which would allow client side rendering again.

If you wish the do server side rendering, have a look at https://angular.io/guide/universal

0
votes

in nodejs return with index.html

 // Redirect all the other requests
    this.app.get('*', (req: Request, res: Response) => {
        if (allowedExt.filter((ext) => req.url.indexOf(ext) > 0).length > 0) {
            res.sendFile(path.resolve(`dist/assets/${req.url.split('?')[0]}`));
        } else {
            res.sendFile(path.resolve('dist/app/index.html'));
        }
    });