docs: add intro to new ssr guide and refactor information architecture (#61377)

PR Close #61377
This commit is contained in:
Ben Hong
2025-05-15 14:11:47 -04:00
committed by Jessica Janiuk
parent 41ded3dbc8
commit 810b3efec0
+72 -70
View File
@@ -1,25 +1,26 @@
# Server and hybrid rendering
Angular ships all applications as client-side rendered (CSR) by default. While this approach delivers a initial payload that's lightweight, it introduces trade-offs including slower load times, degraded performance metrics, and higher resource demands since the user's device performs most of the computations. As a result, many applications achieve significant performance improvements by integrating server-side rendering (SSR) into a hybrid rendering strategy.
## What is hybrid rendering?
Hybrid rendering combines the benefits of server-side rendering (SSR), pre-rendering (also known as "static site generation" or SSG) and client-side rendering (CSR) to optimize your Angular application. It allows you to render different parts of your application using different strategies, giving you fine-grained control over how your app is delivered to users.
Hybrid rendering allows developers to leverage the benefits of server-side rendering (SSR), pre-rendering (also known as "static site generation" or SSG) and client-side rendering (CSR) to optimize your Angular application. It gives you fine-grained control over how your different parts of your app is rendered to give your users the best experience possible.
## Setting up hybrid rendering
You can create a **new** project with server-side rendering with the Angular CLI:
You can create a **new** project with hybrid rendering by using the server-side rendering flag (i.e., `--ssr`) with the Angular CLI `ng new` command:
```shell
ng new --ssr
```
You can also add server-side rendering to an existing project with the `ng add` command:
You can also enable hybrid rendering by adding server-side rendering to an existing project with the `ng add` command:
```shell
ng add @angular/ssr
```
NOTE: By default, Angular prerenders your entire application and generates a server file. To disable this and create a fully static app, set `outputMode` to `static`. To enable SSR, update the server routes to use `RenderMode.Server`.
For more details, see [`Server routing`](#server-routing) and [`Generate a fully static application`](#generate-a-fully-static-application).
NOTE: By default, Angular prerenders your entire application and generates a server file. To disable this and create a fully static app, set `outputMode` to `static`. To enable SSR, update the server routes to use `RenderMode.Server`. For more details, see [`Server routing`](#server-routing) and [`Generate a fully static application`](#generate-a-fully-static-application).
## Server routing
@@ -241,6 +242,31 @@ export const serverRoutes: ServerRoute[] = [
];
```
## Authoring server-compatible components
Some common browser APIs and capabilities might not be available on the server. Applications cannot make use of browser-specific global objects like `window`, `document`, `navigator`, or `location` as well as certain properties of `HTMLElement`.
In general, code which relies on browser-specific symbols should only be executed in the browser, not on the server. This can be enforced through the [`afterEveryRender`](api/core/afterEveryRender) and [`afterNextRender`](api/core/afterNextRender) lifecycle hooks. These are only executed on the browser and skipped on the server.
```angular-ts
import { Component, ViewChild, afterNextRender } from '@angular/core';
@Component({
selector: 'my-cmp',
template: `<span #content>{{ ... }}</span>`,
})
export class MyComponent {
@ViewChild('content') contentRef: ElementRef;
constructor() {
afterNextRender(() => {
// Safe to check `scrollHeight` because this will only run in the browser, not the server.
console.log('content height: ' + this.contentRef.nativeElement.scrollHeight);
});
}
}
```
## Accessing Request and Response via DI
The `@angular/core` package provides several tokens for interacting with the server-side rendering environment. These tokens give you access to crucial information and objects within your Angular application during SSR.
@@ -265,11 +291,52 @@ export class MyComponent {
```
IMPORTANT: The above tokens will be `null` in the following scenarios:
- During the build processes.
- When the application is rendered in the browser (CSR).
- When performing static site generation (SSG).
- During route extraction in development (at the time of the request).
## Generate a fully static application
By default, Angular prerenders your entire application and generates a server file for handling requests. This allows your app to serve pre-rendered content to users. However, if you prefer a fully static site without a server, you can opt out of this behavior by setting the `outputMode` to `static` in your `angular.json` configuration file.
When `outputMode` is set to `static`, Angular generates pre-rendered HTML files for each route at build time, but it does not generate a server file or require a Node.js server to serve the app. This is useful for deploying to static hosting providers where a backend server is not needed.
To configure this, update your `angular.json` file as follows:
```json
{
"projects": {
"your-app": {
"architect": {
"build": {
"options": {
"outputMode": "static"
}
}
}
}
}
}
```
## Caching data when using HttpClient
[`HttpClient`](api/common/http/HttpClient) cached outgoing network requests when running on the server. This information is serialized and transferred to the browser as part of the initial HTML sent from the server. In the browser, `HttpClient` checks whether it has data in the cache and if so, reuses it instead of making a new HTTP request during initial application rendering. `HttpClient` stops using the cache once an application becomes [stable](api/core/ApplicationRef#isStable) while running in a browser.
By default, `HttpClient` caches all `HEAD` and `GET` requests which don't contain `Authorization` or `Proxy-Authorization` headers. You can override those settings by using [`withHttpTransferCacheOptions`](api/platform-browser/withHttpTransferCacheOptions) when providing hydration.
```typescript
bootstrapApplication(AppComponent, {
providers: [
provideClientHydration(withHttpTransferCacheOptions({
includePostRequests: true
}))
]
});
```
## Configuring a server
### Node.js
@@ -322,68 +389,3 @@ export const reqHandler = createRequestHandler(async (req: Request) => {
// ...
});
```
## Generate a fully static application
By default, Angular prerenders your entire application and generates a server file for handling requests. This allows your app to serve pre-rendered content to users. However, if you prefer a fully static site without a server, you can opt out of this behavior by setting the `outputMode` to `static` in your `angular.json` configuration file.
When `outputMode` is set to `static`, Angular generates pre-rendered HTML files for each route at build time, but it does not generate a server file or require a Node.js server to serve the app. This is useful for deploying to static hosting providers where a backend server is not needed.
To configure this, update your `angular.json` file as follows:
```json
{
"projects": {
"your-app": {
"architect": {
"build": {
"options": {
"outputMode": "static"
}
}
}
}
}
}
```
## Caching data when using HttpClient
[`HttpClient`](api/common/http/HttpClient) cached outgoing network requests when running on the server. This information is serialized and transferred to the browser as part of the initial HTML sent from the server. In the browser, `HttpClient` checks whether it has data in the cache and if so, reuses it instead of making a new HTTP request during initial application rendering. `HttpClient` stops using the cache once an application becomes [stable](api/core/ApplicationRef#isStable) while running in a browser.
By default, `HttpClient` caches all `HEAD` and `GET` requests which don't contain `Authorization` or `Proxy-Authorization` headers. You can override those settings by using [`withHttpTransferCacheOptions`](api/platform-browser/withHttpTransferCacheOptions) when providing hydration.
```typescript
bootstrapApplication(AppComponent, {
providers: [
provideClientHydration(withHttpTransferCacheOptions({
includePostRequests: true
}))
]
});
```
## Authoring server-compatible components
Some common browser APIs and capabilities might not be available on the server. Applications cannot make use of browser-specific global objects like `window`, `document`, `navigator`, or `location` as well as certain properties of `HTMLElement`.
In general, code which relies on browser-specific symbols should only be executed in the browser, not on the server. This can be enforced through the [`afterEveryRender`](api/core/afterEveryRender) and [`afterNextRender`](api/core/afterNextRender) lifecycle hooks. These are only executed on the browser and skipped on the server.
```angular-ts
import { Component, ViewChild, afterNextRender } from '@angular/core';
@Component({
selector: 'my-cmp',
template: `<span #content>{{ ... }}</span>`,
})
export class MyComponent {
@ViewChild('content') contentRef: ElementRef;
constructor() {
afterNextRender(() => {
// Safe to check `scrollHeight` because this will only run in the browser, not the server.
console.log('content height: ' + this.contentRef.nativeElement.scrollHeight);
});
}
}
```