En esta página
SSR, pre-rendering y despliegue
Qué es SSR?
Server-Side Rendering (SSR) genera el HTML de tu aplicación en el servidor antes de enviarlo al navegador. Beneficios:
- SEO mejorado — Los bots de busqueda leen HTML completo
- Primera carga rápida — El usuario ve contenido inmediatamente
- Social sharing — Meta tags disponibles para Open Graph
Modos de renderizado en Angular 21
Angular 21 define tres modos en ServerRoute:
| Modo | Descripcion | Cuando usar |
|---|---|---|
RenderMode.Prerender |
HTML generado en build time | Páginas estaticas (home, about, blog) |
RenderMode.Server |
HTML generado por request | Páginas dinamicas (perfiles, busqueda) |
RenderMode.Client |
Solo renderizado en el navegador | Dashboard, admin, contenido privado |
Configurar SSR
Al crear un proyecto con ng new, Angular pregunta si quieres SSR. Si ya tienes un proyecto, agregalo con:
ng add @angular/ssrEsto genera:
src/app/app.config.server.ts— Configuración del servidorsrc/app/app.routes.server.ts— Rutas con modos de renderizadoserver.ts— Servidor Express
Rutas del servidor
Define como se renderiza cada ruta:
import { RenderMode, ServerRoute } from '@angular/ssr';
export const serverRoutes: ServerRoute[] = [
// Pre-renderizar en build
{ path: '', renderMode: RenderMode.Prerender },
{ path: 'blog', renderMode: RenderMode.Prerender },
// Pre-renderizar con parametros (genera un HTML por slug)
{
path: 'blog/:slug',
renderMode: RenderMode.Prerender,
async getPrerenderParams() {
return [
{ slug: 'introduccion-angular' },
{ slug: 'signals-tutorial' },
{ slug: 'ssr-guia-completa' },
];
},
},
// SSR dinámico
{ path: 'buscar', renderMode: RenderMode.Server },
// Solo cliente
{ path: 'dashboard/**', renderMode: RenderMode.Client },
];Deteccion de plataforma
Algunos APIs solo existen en el navegador. Usa isPlatformBrowser para proteger ese código:
import { isPlatformBrowser, PLATFORM_ID } from '@angular/common';
import { inject } from '@angular/core';
const platformId = inject(PLATFORM_ID);
if (isPlatformBrowser(platformId)) {
// Seguro: estamos en el navegador
window.scrollTo(0, 0);
localStorage.setItem('key', 'value');
}afterNextRender y afterRender
Para código que debe ejecutarse solo despues del renderizado en el navegador:
import { afterNextRender } from '@angular/core';
constructor() {
afterNextRender(() => {
// Se ejecuta una vez, solo en el navegador
// Ideal para inicializar librerias de terceros
this.chart = new Chart(this.canvasRef.nativeElement, config);
});
}Meta tags para SEO
Usa los servicios Title y Meta para establecer meta tags server-side:
import { Title, Meta } from '@angular/platform-browser';
@Component({ /* ... */ })
export class BlogPost {
private readonly title = inject(Title);
private readonly meta = inject(Meta);
constructor() {
effect(() => {
const post = this.post();
this.title.setTitle(`${post.título} | Mi Blog`);
this.meta.updateTag({ name: 'description', content: post.resumen });
this.meta.updateTag({ property: 'og:title', content: post.título });
this.meta.updateTag({ property: 'og:image', content: post.imagen });
});
}
}Despliegue
Firebase Hosting (estático + Cloud Functions)
ng build
firebase deployDocker (SSR completo)
FROM node:20-alpine
WORKDIR /app
COPY dist/ ./dist/
COPY package.json ./
RUN npm install --production
EXPOSE 4000
CMD ["node", "dist/mi-app/server/server.mjs"]Plataformas compatibles
- Firebase Hosting — Pre-rendering estático + Cloud Functions
- Vercel — SSR serverless automático
- Netlify — Pre-rendering estático
- Railway / Render — SSR con Docker
Práctica
- Configura modos de renderizado: Define un archivo
app.routes.server.tscon al menos 3 rutas usando los tres modos:Prerenderpara la pagina principal,Serverpara rutas dinamicas yClientpara el dashboard. - Protege APIs del navegador: Crea un servicio que use
localStorage. Envuelvelo conisPlatformBrowser()para que no falle durante SSR y agrega un fallback para el servidor. - Agrega meta tags SEO: Usa los servicios
TitleyMetadentro de uneffect()para establecer el titulo de la pagina y las etiquetasdescriptionyog:titledinamicamente en un componente.
En la siguiente leccion aprenderemos los fundamentos de testing en Angular con Vitest.
// --- app.config.server.ts ---
import { ApplicationConfig, mergeApplicationConfig } from '@angular/core';
import { provideServerRendering } from '@angular/platform-server';
import { provideServerRoutesConfig } from '@angular/ssr';
import { serverRoutes } from './app.routes.server';
import { appConfig } from './app.config';
const serverConfig: ApplicationConfig = {
providers: [
provideServerRendering(),
provideServerRoutesConfig(serverRoutes),
],
};
export default mergeApplicationConfig(appConfig, serverConfig);
// --- app.routes.server.ts ---
import { RenderMode, ServerRoute } from '@angular/ssr';
export const serverRoutes: ServerRoute[] = [
// Páginas estaticas: se pre-renderizan en build
{ path: '', renderMode: RenderMode.Prerender },
{ path: 'blog', renderMode: RenderMode.Prerender },
{ path: 'cursos', renderMode: RenderMode.Prerender },
// Páginas con parametros: SSR en el servidor
{
path: 'blog/:slug',
renderMode: RenderMode.Server,
},
// Dashboard: solo cliente (no SSR)
{ path: 'dashboard/**', renderMode: RenderMode.Client },
// Ruta catch-all
{ path: '**', renderMode: RenderMode.Server },
];
Inicia sesión para guardar tu progreso