mirror of
https://github.com/angular/angular
synced 2026-05-24 09:28:37 +00:00
docs: add platform-specific implementation and helpers
(cherry picked from commit 0c7508bf56)
This commit is contained in:
parent
2935fef3af
commit
ea45b4d54c
1 changed files with 71 additions and 0 deletions
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Reference in a new issue