4

I've seen many questions here that address this but using an apache server, for my application, I'm using AWS S3 with Cloudfront, I need the application to work without the ugly hash on the URL.

Is there any approach that can be done to be able to refresh, or hit links directly without using the hash?

If any part of the code is required I can include it but I don't see the need for it since nothing is failing, I just need a working strategy.

Regards.

My app routing module

@NgModule({
  imports: [
    RouterModule.forRoot(routes, { useHash: true })
  ],
  exports: [
    RouterModule
  ]
})

Removing the hash true works for navigation but not for page refresh or direct links

Artem Arkhipov
  • 7,025
  • 5
  • 30
  • 52
DJ22T
  • 1,628
  • 3
  • 34
  • 66
  • 1
    Have you checked https://stackoverflow.com/questions/54611652/angular-routing-is-not-working-with-cloudfront-and-s3 already? – kgiannakakis Oct 20 '21 at 05:24
  • `I need the application to work without the ugly hash` why? What do you want to achieve? – gusto2 Nov 20 '21 at 17:57
  • Well, the Product Management thinks the hash is not friendly and it doesn't work for them. I can live with it but I don't make the requirements sadly. – DJ22T Nov 20 '21 at 18:58
  • Check the configuration for the 404. It should return index.html https://stackoverflow.com/questions/43101013/custom-404-page-for-static-website-using-aws-s3-buckets-not-working – Sergey Nov 20 '21 at 19:05

2 Answers2

9

Before writing the solution, let me shortly explain what is needed to be done. In general, page navigation in single page applications (SPA) is achieved by javascript code manipulating the view and/or monitoring the url and navigation history events. When you launch the app and click different links, for example /user, application is not reloaded, it is still the same app loaded via root index.html which reacts to the clicked link by changing to the corresponding view or component and modifying the url in the address bar.

However, if you navigate to the example.com/user directly after opening browser (without initial load of the root example.com), browser will send request to the /user path which doesn't actually exist nor in S3 bucket, neither in cloudfront distribution, though it will be failed. Our aim is to force S3 and Cloudfront to always return the root index.html file, independently of what was the original path of the request.

In order to achieve that you need slightly change the configuration of S3 bucket and Cloudfront distribution.

Before moving to the AWS related changes, change the useHash property of the RouterModule import to false:

RouterModule.forRoot(routes, { useHash: false })
  1. Open your S3 bucket in the AWS web console, go to the "properties" tab, find the "static website hosting" section, enable it if it was disabled and put index.html into both fields: index document and error document.

enter image description here

Then save the configuration. Actually now your index.html file will be served for any path same as for the root one. You should already notice that when you open your website after above changes applied. However, you will notice that the response code is 404 despite application opens correctly - it happens because it is still the "not found" response as the path doesn't exist. There are some changes needed in the cloudfront configuration too to make this working even better.

  1. Navigate to the cloudfront distribution page in aws web console. I assume that since you already have cloudfront distribution (you mentioned it in the question) then you probably have all the default setups already and your S3 bucket is already connected as an origin for this distribution. Navigate to the "error pages" tab and press "create new custom error response". Click "yes" in the "customize" input, select error code 404, write "/index.html" in the "response page path" input and select code 200OK for the response. Then save the configuration. It may take a few minutes to start working.

enter image description here

Now try to open the website - you should not see 404 responses anymore because now all the requests (even to not existing paths) have code 200.

Artem Arkhipov
  • 7,025
  • 5
  • 30
  • 52
0

Remove hash strategy,

RouterModule.forRoot(routes, {
  useHash: false
});

Go to your bucket's Static website hosting setting and set Error document to index.html.

Basically, we just want to serve index.html in all the case as that's the file that must be served in all the cases as angular build is not having folder structure for routes like static websites.

Now your routes will look like:

localhost:4200/home

Instead of:

localhost:4200/#/home

Reference from AWS: https://docs.aws.amazon.com/AmazonS3/latest/userguide/CustomErrorDocSupport.html#custom-error-document

Zee
  • 483
  • 3
  • 10