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.
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));
// Enables navigation with a trailing slash without removing it
const __stripTrailingSlash = (Location as any).stripTrailingSlash;
(Location as any).stripTrailingSlash = function _stripTrailingSlash(url: string): string {
// Split the URL into three parts: the path before the question mark, the query string, and the fragment
const urlParts = url.match(/([^?#]*)(\?[^#]*)?(#.*)?/);
const path = urlParts?.[1] || ""; // Path before query and fragment
const queryString = urlParts?.[2] || ""; // Query string (optional)
const fragment = urlParts?.[3] || ""; // Fragment (optional)
// If the path ends with a slash, add a dot before the query string or fragment
if (/[^\/]\/$/.test(path)) {
return path + "." + queryString + fragment;
}
// If the path does not end with a slash, call the original stripTrailingSlash method
return __stripTrailingSlash(url);
};
All route paths in Angular must have a trailing slash, followed by a dot.
export const routes: Routes = [
{ path: "", loadComponent: () => import("./routes/home/home.component").then((m) => m.HomeComponent) },
{ path: "legal-notice/.", loadComponent: () => import("./routes/legal-notice/legal-notice.component").then((m) => m.LegalNoticeComponent) },
{ path: "legal-notice", loadComponent: () => import("./routes/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