The Angular Application Builder pre-renders an Angular project, but is designed for deployment with a backend. By default, all requests run via server.mjs, which runs in the backend via Node. In order to be able to use the Application Builder for a deployment with only the pre-rendered files, a few things have to be taken into account.

The project is pre-rendered with the ng build command. The pre-rendered files can be found in the dist/projectname/browser/ directory. The Application Builder has created a separate directory for each route, which has the name of the route and contains an index.html. If you start an HTTP server in this directory, you can already test the pre-rendered page.

The trailing slash problem

Without further adjustments, you will encounter a problem in the network tab of the developer tools: When you call up the page, a redirect occurs. The request is made without a slash at the end of the URL and is then redirected to the URL with a trailing slash.

302 Redirect

The reason for this is that the HTTP server is looking for a file but finds a directory. When requesting domain.de/legal-notice, the HTTP server tries to find the file domain.de/legal-notice.html. Since this file does not exist, the redirection to domain.de/legal-notice/index.html occurs. To prevent the redirection, the URL domain.de/legal-notice/ should be called directly.

Now the problem remains that Angular changes the URL to domain.de/legal-notice after calling domain.de/legal-notice/. This leads again to the problem with the redirection when reloading the page. The following script in main.ts prevents Angular from removing the trailing slash:

import { Location } from "@angular/common";
import { bootstrapApplication } from "@angular/platform-browser";
import { AppComponent } from "./app/app.component";
import { appConfig } from "./app/app.config";

bootstrapApplication(AppComponent, appConfig).catch((err) => console.error(err));

const __stripTrailingSlash = Location.stripTrailingSlash;

// Enables navigation with a trailing slash without removing it
Location.stripTrailingSlash = function _stripTrailingSlash(url: string): string {
  const urlParts = url.match(/([^?#]*)(\?[^#]*)?(#.*)?/);

  const path = urlParts?.[1] || "";
  const query = urlParts?.[2] || "";
  const fragment = urlParts?.[3] || "";

  // If the path ends with a slash, add a dot
  return /[^\\/]\/$/.test(path) ? path + "." + query + fragment : __stripTrailingSlash(url);
};

All route paths in Angular must have a trailing slash, followed by a dot.

export const routes: Routes = [
  {
    path: "",
    loadComponent: () => import("./home/home.component").then((m) => m.HomeComponent),
  },
  {
    path: "legal-notice/.",
    loadComponent: () => import("./legal-notice/legal-notice.component").then((m) => m.LegalNoticeComponent),
  },
  {
    path: "legal-notice",
    loadComponent: () => import("./legal-notice/legal-notice.component").then((m) => m.LegalNoticeComponent),
  },
];

The call must also end with a period:

<a routerLink="/legal-notice/.">legal-notice</a>

Testing the pre-rendered page

The pre-rendered page should be tested before deployment.

Change to the directory

cd dist/projektname/browser

Starting the HTTP server

http-server

Deployment on GitHub Pages

The directory dist/projectname/browser/ must be uploaded to GitHub Pages. This can be done either manually or with the help of angular-cli-ghpages.

The deployment is just one command:

npx angular-cli-ghpages --dir=dist/projektname/browser --cname=domain.com