This article is about deploying an Angular 6 application to Pivotal Cloud Foundry so that URLs without a hash can be used.
First, some Angular background. Angular is a SPA-framework which means that an Angular app has exactly one html-file: the index.html. This is the only file a web server knows, that’s why theoretically there is only one URL: the one pointing to index.html. However in Angular, it’s possible to create routes like mydomain.com/sub. Because there is no sub.html file, a request directly to this file will result in a 404 error because the web server cannot serve a non-existing file. To allow defining and visiting those paths, Angular has a build-in solution. The RouterModule, which is responsible for creating routes like the before mentioned /sub, can be configured to insert hashes in each URL:
Those hashes separate the known URL to the existing index.html and the additional path, for example in “mydomain.com/#/sub”. The web server will forward the request to the index.html which will deliver the requested and dynamically created Angular-content.
However, using hashes in URLs is not pretty, so I wanted to get rid of them.
Approach 1: Using staticfile_buildpack with modified nginx.conf
Setting up a new Angular application can be done quickly by using the staticfile-buildpack which simply serves the Angular application without much configuration. Here’s the manifest.yml for this simple case:
The first approach to removing the hashes is to remove the useHash-parameter in the application source code:
This will lead to clean URLs that work when accessed from “within” the Angular application: If you call the base URL mydomain.com which resolves to the index.html and navigate from there to other paths like mydomain.com/sub, everything will work. However, direct requests to this path will result in a 404 error. This is also true for refreshing an opened Angular application with F5.
The nginx-server, which is the web server used in Pivotal Cloud Foundry, can be configured to forward every request to index.html and thereby to Angular. Copying the nginx.conf-file from a preciously successfully deployed and running server is a good way of getting a definitively working config file that can be modified. Another way of getting this file is via Github. This is the modification to forward every request to index.html:
Simply changing nginx.conf on a deployed server is not a good solution because the container gets rebuild with every new deployment. Hence, putting the modified version in the local dist-folder (next to index.html) will upload it with the next deployment. Simply adding the try_files-configuration and using the staticfile_buildpack will solve the URL-hash-problem, but at a cost. Starting the server will bring the following warning:
Approach 2: Using nginx-buildpack with modified nginx.conf
To use the right buildpack, it has to be referenced in the manifest.yml:
Also, the structure of the dist-folder has to be as follows:
The public-folder is where all the Angular-generated files will be. mime.types can be copied from the nginx-buildpack Github account, as well as a simple version of nginx.conf. It is very important to use in the nginx.conf.
This setup will lead to clean, hash-free URLs as well as no warnings when deploying.