5

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.

3
  • Do you have nginx before node.js or not? Commented Sep 16, 2019 at 8:26
  • 1
    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/… Commented Sep 16, 2019 at 9:44
  • What server are you using? Commented Sep 19, 2019 at 13:11

7 Answers 7

3
+150

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).

Sign up to request clarification or add additional context in comments.

1 Comment

Sorry for the late reply, I have gone through all answers, some are not relevant even though I checked, This is the simplest solution I got. And It works like charm. e.g. RouterModule.forRoot(paths, { useHash: true })
3

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.

4 Comments

Are you suggesting to dynamically route from angular root?
You have to, if you want to use the normal angular routing. Your server only knows the angular-base-route and the whole angular application works on it. Everything else is angular magic.
To add on to @Gollm, in a normal web server, when you try to access /category/fruits.html, the web server looks for fruits.html file in /category directory (folder). If it exists, the html file is served. If not, 404 is returned. Angular, however, has it's own internal routing implementation. When you access /category, the web server again tries to find /category directory, which it wouldn't find. So it correctly returns 404. This is why you have to route a 404 response to /index.html which will trigger Angular's internal routing to /Category route.
You can observe this when you run ng s anyway, you will see this line: 「wds」: 404s will fallback to //index.html.
1

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;
    }
}

Comments

0

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.

Comments

0

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.

Comments

0

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

Comments

0

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'));
        }
    });

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.