Angular
headless-prerender works with a client-side Angular app (the default ng build output) when Angular Universal / SSR is not in use.
When you need it
index.html bootstraps into <app-root>:
<app-root></app-root>
<script src="main.js" type="module"></script>Non-JS crawlers see an empty <app-root>. The prerender service returns the rendered DOM.
Consider Angular SSR first
Angular has first-class server-side rendering (ng add @angular/ssr). If you can adopt it, that is the better long-term option. Use headless-prerender when SSR is not currently feasible.
Setup
Deploy the browser build (
dist/<app>/browser) as static files.Run the service:
bashheadless-prerender serve \ --port 3000 \ --allow-origin https://www.example.com \ --cache-ttl 300000
Waiting for stability
Angular apps often settle quickly, but HTTP calls in ngOnInit or route resolvers may land after network idle. Add settle time:
headless-prerender serve --extra-wait 500For a deterministic signal, set a flag when the app is stable:
import { ApplicationRef } from "@angular/core";
import { first } from "rxjs/operators";
constructor(appRef: ApplicationRef) {
appRef.isStable.pipe(first((stable) => stable)).subscribe(() => {
(window as any).__PRERENDER_READY__ = true;
});
}Meta tags
Use Angular's Title and Meta services per route:
constructor(private title: Title, private meta: Meta) {}
ngOnInit() {
this.title.setTitle(this.product.name);
this.meta.updateTag({ property: "og:title", content: this.product.name });
this.meta.updateTag({ property: "og:description", content: this.product.summary });
}The renderer captures the resulting <head>.
404 status codes
Render a status-code meta tag on your not-found route and have the proxy read it:
this.meta.updateTag({ name: "prerender-status-code", content: "404" });Checklist
- [ ] SPA fallback to
index.htmlconfigured on the host - [ ]
--allow-originset - [ ]
--extra-waitcovers resolver / HTTP latency - [ ]
Title/Metaset per route - [ ] 404 routes marked
- [ ] Caching enabled