How to handle deep links in Angular?

Viewed 21396

There has been a lot of questions about this. I've been browsing them for days. I tried everything, and neither worked. Yes, I've checked angular.io too, and that didn't work either. So please, can someone come up with the ultimate answer or point me to one which I've probably not seen yet?

Here is this URL, a deep link to an Angular app called whatever and its someroute route with a parameter.

http://somedomain.com/whatever/someroute/123456

Of course it results in a 404 error. The web server has to be configured. My server runs nginx and I did this:

location / {
     try_files $uri $uri/ /whatever/index.html;
}

Now it redirects every site's 404 error on this server to my Angular app, but that's a secondary issue. The problem is that the route still doesn't want to kick in. The default / route is invoked every time, and not /someroute/123456.

Instead of pointing to various tutorials which I've probably already seen and tried, can someone briefly explain what is the trivial point I missed?

4 Answers

It sounds like you may be missing the <base href=""> tag. This tag tells the Angular router what the base URI is for your application. If this is not present then Angular assumes that the initial navigation URI (in your case, /whatever/someroute/123456) is the base URI and all subsequent routing will be performed relative to that URI.

Try including <base href="/whatever/"> in the <head> element of your index.html to direct the router accordingly.

You may also control the <base href=""> meta tag via ng build if you are using the Angular CLI:

ng build --base-href '/whatever/'

You can switch to the HashLocationStrategy, i.e.

RouterModule.forRoot(appRoutes, {useHash: true});

This results in all app urls being index.html, followed by "#" and then the routing information.

Since you're always going to index.html, regardless of the route, you won't get a 404 for any valid URL.

This was tripping me up for a while too. But just for the record, the Angular deployment documentation has a good section about this which you can find here https://angular.io/guide/deployment#server-configuration

The bottom line is that if you navigate from outside your app to a location in your app (other than the root location "/") the browser sends a GET request to the server asking for the full URL. But since that URL is meant to be interpreted as a route in your front-end app and not as a resource in your back-end server the server will throw a 404 (unless you happen to have also set up your server as a static file server and there happens to be a resource at that location). So what you need to do is configure your server to respond with the front-end app assets instead of returning a 404, that way when the front-end app loads in the browser it can check the URL and engage it's routing logic.

I experienced the same difficulties to get NGINX 1.17 to work in combination with routing in Angular 9. I finally found an NGINX configuration that supports deep linking respectively routing and at the same time doesn't require the usage of Angular's HashLocationStrategy nor setting <base href="">.

The key difference that I made is that I added the root directive to the location block to specify the root directory that will be used to search for a file:

events {
    worker_connections 1024;
}

http {

    server {
        listen 80;

        location / {
            root /usr/share/nginx/html;
            try_files $uri $uri/ /index.html;
        }
    }
    include /etc/nginx/mime.types;
}

This NGINX configuration assumes that the content of Angular's dist folder resides in /usr/share/nginx/html/. With this configuration I don't experience any HTTP 404 errors for routes like /someroute/123456 (even when I reload the page in the browser by hitting F5 or when I navigate to this route directly).

Related