docs: add platform-specific implementation and helpers

(cherry picked from commit 0c7508bf56)
This commit is contained in:
SkyZeroZx 2025-12-01 15:01:37 -05:00 committed by Pawel Kozlowski
parent 2935fef3af
commit ea45b4d54c

View file

@ -267,6 +267,10 @@ export class MyComponent {
}
```
NOTE: Prefer [platform-specific providers](guide/ssr#providing-platform-specific-implementations) over runtime checks with `isPlatformBrowser` or `isPlatformServer`.
IMPORTANT: Avoid using `isPlatformBrowser` in templates with `@if` or other conditionals to render different content on server and client. This causes hydration mismatches and layout shifts, negatively impacting user experience and [Core Web Vitals](https://web.dev/learn-core-web-vitals/). Instead, use `afterNextRender` for browser-specific initialization and keep rendered content consistent across platforms.
## Setting providers on the server
On the server side, top level provider values are set once when the application code is initially parsed and evaluated.
@ -274,6 +278,73 @@ This means that providers configured with `useValue` will keep their value acros
If you want to generate a new value for each request, use a factory provider with `useFactory`. The factory function will run for every incoming request, ensuring that a new value is created and assigned to the token each time.
## Providing platform-specific implementations
When your application needs different behavior on the browser and server, provide separate service implementations for each platform. This approach centralizes platform logic in dedicated services.
```ts
export abstract class AnalyticsService {
abstract trackEvent(name: string): void;
}
```
Create the browser implementation:
```ts
@Injectable()
export class BrowserAnalyticsService implements AnalyticsService {
trackEvent(name: string): void {
// Sends the event to the browser-based third-party analytics provider
}
}
```
Create the server implementation:
```ts
@Injectable()
export class ServerAnalyticsService implements AnalyticsService {
trackEvent(name: string): void {
// Records the event on the server
}
}
```
Register the browser implementation in your main application configuration:
```ts
// app.config.ts
export const appConfig: ApplicationConfig = {
providers: [
{ provide: AnalyticsService, useClass: BrowserAnalyticsService },
]
};
```
Override with the server implementation in your server configuration:
```ts
// app.config.server.ts
const serverConfig: ApplicationConfig = {
providers: [
{ provide: AnalyticsService, useClass: ServerAnalyticsService },
]
};
```
Inject and use the service in your components:
```ts
@Component({/* ... */})
export class Checkout {
private analytics = inject(AnalyticsService);
onAction() {
this.analytics.trackEvent('action');
}
}
```
## Accessing Document via DI
When working with server-side rendering, you should avoid directly referencing browser-specific globals like `document`. Instead, use the [`DOCUMENT`](api/core/DOCUMENT) token to access the document object in a platform-agnostic way.