Angular SPA Preset
Preset file: presets/angular-spa.toml
Works with Angular 14+ in both standalone and module-based configurations.
Overview
Angular applications bootstrap into an <app-root> component and use Zone.js to track asynchronous operations. Angular's compiler generates _ngcontent-* and _nghost-* attributes for view encapsulation, and ng-* attributes for framework directives.
Key Configuration
[render]
wait_for = "networkidle"
timeout_secs = 15
[render.postprocess]
enabled = true
strip_scripts = true
strip_noscript = true
strip_comments = true
strip_event_handlers = true
strip_hydration_attrs = true # Removes ng-*, _ngcontent-*, _nghost-*
resolve_lazy_images = true
[render.content_validation]
enabled = true
min_text_length = 100
require_title = true
min_html_bytes = 1024
Zone.js and networkidle
Angular uses Zone.js to track all asynchronous operations (HTTP requests, timers, promises). The networkidle wait strategy works well with Angular because Zone.js ensures that all data fetching completes before the framework considers the view stable.
If your Angular app has background polling or WebSocket connections, these can prevent networkidle from resolving. In that case, use a selector wait:
[render]
wait_for = "app-root .content-loaded"
Hydration Attribute Stripping
With strip_hydration_attrs = true, PRISM removes:
| Attribute | Purpose in Angular | Why It's Stripped |
|---|---|---|
ng-version | Angular version marker | Debugging only |
ng-reflect-* | Template binding debug info | Development mode only, but sometimes leaks to prod |
_ngcontent-* | View encapsulation scope ID | Only meaningful with Angular's emulated CSS scoping |
_nghost-* | Host element scope ID | Only meaningful with Angular's emulated CSS scoping |
Before:
<app-root _nghost-abc="" ng-version="17.0">
<div _ngcontent-abc="" class="container">
<h1 _ngcontent-abc="">Products</h1>
</div>
</app-root>
After:
<app-root>
<div class="container">
<h1>Products</h1>
</div>
</app-root>
Angular Universal (SSR)
If your Angular app uses Angular Universal for server-side rendering, PRISM is typically unnecessary. However, PRISM can still help with:
- Pages that rely heavily on client-side data fetching after SSR.
- Hybrid apps where some routes are SSR and others are CSR.
- Legacy Angular apps that cannot easily adopt Universal.
Route Exclusions
The preset excludes Angular-specific assets:
[routes]
exclude = [
"/api/**",
"**/*.js", "**/*.css", "**/*.json", "**/*.xml",
"**/*.png", "**/*.jpg", "**/*.gif", "**/*.svg", "**/*.ico",
"**/*.woff", "**/*.woff2", "**/*.ttf", "**/*.wasm", "**/*.map",
"/assets/**",
"/manifest.json", "/ngsw.json", "/ngsw-worker.js",
"/robots.txt", "/sitemap.xml",
]
Note the Angular-specific exclusions: /ngsw.json and /ngsw-worker.js are Angular's service worker files.
Full Preset
[render]
wait_for = "networkidle"
timeout_secs = 15
[render.postprocess]
enabled = true
strip_scripts = true
strip_noscript = true
strip_comments = true
strip_event_handlers = true
strip_hydration_attrs = true
resolve_lazy_images = true
[render.content_validation]
enabled = true
min_text_length = 100
require_title = true
min_html_bytes = 1024
[routes]
include = ["/**"]
exclude = [
"/api/**",
"**/*.js", "**/*.css", "**/*.json", "**/*.xml",
"**/*.png", "**/*.jpg", "**/*.gif", "**/*.svg", "**/*.ico",
"**/*.woff", "**/*.woff2", "**/*.ttf", "**/*.wasm", "**/*.map",
"/assets/**",
"/manifest.json", "/ngsw.json", "/ngsw-worker.js",
"/robots.txt", "/sitemap.xml",
]