Social media links

Understanding Angular client side routing

Image generated by DALL-E

When working with Angular or with single page applications frameworks (SPA), the routing is done client side using JavaScript. In Angular it is based on the concept of a router, which is responsible for mapping URLs (paths) to components of the application.

If you are interested to read about the differences between single page applications that use client side routing and multi page application that use a server side routing, I invite you to check my other article https://lucasarcuri.com/blog/single-page-applications-vs-multi-page-applications/

What is client side routing

Client side routing is a technique used in modern web application to dynamically change the content displayed to the user based on the URL path they are accessing. Unlike traditional server side routing that sends the entire page to the user when users request a new page, client side routing allow the application to remain on a single page while changing part of the content displayed in the browser.

In web applications using client side routing, there is typically a router module that manages the mapping of URLs to different parts of the application. In case of Angular, this is the RouterModule.

Understanding how your application is served and content loaded

Angular application are served to the client through a web server, such as Apache or Nginx. When a request is done, the server responds by serving the main application file, which is the index.html.

Once the index.html is loaded in the browser, it contains references to the various assets, CSS, images, and JavaScript. Once the assets are fetched, the JavaScript files containing the Angular code application logic execute, and your app is injected in the app-root tag.

No matter the path requested, first the index.html needs to be loaded and then client side routing will take the relay.

Angular routing strategy

Angular provides two different routing strategies to handle the navigation of routes in the application. These strategies determines how the router updates the browser’s URL and how it navigate between routes.

HashLocationStrategy

This routing strategy uses URLs fragment (or hash) to match routes. e.g. :

  • https://myapp.com#home
  • https://myapp.com#menu/drinks/cola

It is especially handy for applications that don't have a server side implementation or if for XYZ reasons you can’t configure the server to handle URLs changes.

It is important to understand that with this strategy, the fragment part (everything after the ‘#’) is never sent to the server.

To enable the HashLocationStategy, you need to pass {useHash: true} when you provide the routes to the RouterModule.

RouterModule.forRoot(routes, {useHash: true})

PathLocationStrategy

This is the default routing strategy in Angular. It uses URL path and the HTML5 history API pushstate to change the URL and not have the browser sending a request to the server to load a new page.

However, this works only if you navigate inside the app by using the Angular Router methods, or the routerLink directive.

If you refresh the page or use a ‘normal’ href link, the request will be sent to the server and, unlike the fragment strategy, if you don’t have a proper redirection rules set on your server, you might end up with a 404. This is because, as explained in the section above, in case of fragment URLs, the hash part is not sent to the server, so the server is only asked for the root of your application.

In case of PathLocationStrategy, the server, by default, will try to serve the index content matching your URL. e.g. https://myapp.com/menu, here the server will look for an index.html page under /menu. You need to configure the server to redirect all the requests to your Angular application index.html in the root.

Configure your server to correctly serve your Angular application

As explained through this article, for Angular app using the default PathLocationStrategy, the server needs to be configured to serve the application root index.htmlfor all URLs requested.

Apache server

On Apache server, create a .htaccess file to the root directory of the Angular application with the following configuration:

<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 server

For Nginx, in your .conf file, you need to add a new location rule in your server block:

server {
  listen 80;
  server_name myapp.com;
  root /var/www/myapp;
  index index.html;

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

Base HREF

In case your Angular application is not hosted as the root of your server, you need to specify the base href from which the browser will ask your server to resolve the assets files (image, css, javascript).

If your application is hosted at https://myapp.com/section and you don’t specify the base href, by default the browser will request the assets from the root of your server. e.g. https://myapp.com/main.js instead of https://myapp.com/section/main.js.

You can either specify the base href in head section of the index.html manually:

<base href="/section/">

Or pass it as parameter in your build command:

ng build --base-href /section/

In case your server configuration require to have the URLs requested containing “index.html”, you can also add it in the base href:

ng build --base-href /section/index.html