Introduction: How Your Angular App Comes to Life
Welcome back, future Angular architect! In the previous chapters, we laid the groundwork for understanding Angular’s core. Now, it’s time to tackle one of the most fundamental decisions in frontend system design: How does your application actually show up in the user’s browser?
The way a web application renders its initial content and becomes interactive has a profound impact on its performance, search engine optimization (SEO), and overall user experience. Imagine waiting for a blank screen or a page that looks ready but doesn’t respond to clicks – frustrating, right? This is where rendering strategies come into play.
In this chapter, we’ll explore the spectrum of rendering options available for modern Angular applications: from the traditional Single Page Application (SPA) to Server-Side Rendering (SSR), Static Site Generation (SSG), and the powerful hybrid approaches that combine the best of these worlds. We’ll dive into what each strategy is, why you’d choose it, its pros and cons, and crucially, how Angular helps you implement them using the latest features like @angular/ssr and built-in hydration.
Get ready to make informed architectural decisions that will define the initial impression and long-term success of your Angular applications!
Core Concepts: A Spectrum of Rendering
Let’s break down the primary rendering strategies, understanding their mechanisms, benefits, drawbacks, and common pitfalls in real-world scenarios.
1. Single Page Application (SPA): Client-Side Rendering
The Single Page Application (SPA) model is what most Angular developers start with. In an SPA, the browser downloads a minimal HTML file (often just a <div id="root"></div> or <app-root></app-root>), and then a large JavaScript bundle. The JavaScript code then takes over, fetches data, builds the entire user interface (UI) dynamically, and handles all subsequent navigation without full page reloads.
How it Works:
- User requests a URL.
- Server sends a barebones HTML file and a JavaScript bundle.
- Browser downloads and executes the JavaScript.
- JavaScript fetches data (e.g., from an API).
- JavaScript constructs and renders the UI onto the page.
- The UI becomes interactive.
Why Choose SPA?
- Rich, App-like Experience: Once loaded, navigation is incredibly fast, feeling more like a native desktop application.
- Reduced Server Load (Post-Initial): After the initial bundle delivery, the server primarily acts as an API provider, reducing rendering workload.
- Great for Highly Interactive Dashboards: If your application is behind a login and requires constant user interaction, the SPA model excels.
Downsides & Production Failure Scenario: “The Ghostly Page Load”
- Initial Load Time (Blank Screen): Until the JavaScript bundle is downloaded, parsed, and executed, the user sees a blank page. On slow networks or low-end devices, this can lead to a perceived delay and user abandonment.
- SEO Challenges: Search engine crawlers traditionally prefer fully rendered HTML. While modern crawlers are better at executing JavaScript, relying solely on client-side rendering can still negatively impact SEO, especially for public-facing content.
- Performance on Low-End Devices: Large JavaScript bundles can strain CPU and memory on less powerful devices, leading to slower hydration and overall sluggishness.
Failure Scenario: The Ghostly Page Load
Imagine a user on a patchy mobile network trying to access your public-facing SPA. They click a link, and for several seconds, they stare at a blank white screen with perhaps a tiny spinner, or nothing at all. They might wonder if the site is broken, get impatient, and navigate away. Meanwhile, a search engine crawler visits the page, sees an empty <app-root> tag, and indexes little to no content, harming your search rankings.
Architectural Diagram (SPA):
2. Server-Side Rendering (SSR): Angular Universal
Server-Side Rendering (SSR) flips the script. Instead of sending a blank HTML page, the server pre-renders the initial HTML for a requested route. This means when the browser receives the response, it already contains the full content, which can be displayed almost immediately. After the HTML is displayed, the client-side JavaScript then “hydrates” this static content, making it interactive. Angular’s official solution for SSR is Angular Universal.
How it Works:
- User requests a URL.
- Server executes the Angular application (using Node.js, for example).
- Angular renders the page into a full HTML string on the server.
- Server sends this fully formed HTML, along with the JavaScript bundle, to the browser.
- Browser quickly displays the HTML (fast First Contentful Paint).
- Browser downloads and executes the JavaScript.
- Angular on the client “hydrates” the existing HTML, attaching event listeners and making it interactive.
Why Choose SSR?
- Faster First Contentful Paint (FCP): Users see meaningful content much quicker, improving perceived performance.
- Better SEO: Search engine crawlers receive fully rendered HTML, making it easier for them to index your content accurately.
- Improved Performance on Low-End Devices: Since the initial render happens on the server, less processing power is required on the client to get content on screen.
Downsides & Production Failure Scenario: “The Janky Hydration”
- Increased Server Load/Costs: The server has to do more work per request, executing the Angular application. This can increase server resource consumption and hosting costs.
- Time To First Byte (TTFB): While FCP is faster, the TTFB (the time it takes for the first byte of the response to arrive) can be higher than an SPA if the server-side rendering process is slow or complex.
- Complexity with Hydration: Ensuring the server-rendered HTML perfectly matches what the client-side Angular app expects can be tricky. Mismatches can lead to issues during hydration.
Failure Scenario: The Janky Hydration A user navigates to an SSR-enabled page. The content appears almost instantly, which is great! They try to click a button or interact with a form, but nothing happens for a brief moment. Then, the UI might flicker, re-render slightly, or suddenly become interactive. This “jank” or delay between seeing content and being able to interact with it is caused by hydration issues, where the client-side JavaScript struggles to smoothly take over from the server-rendered HTML. It can be a confusing and frustrating experience, sometimes even worse than a blank page because the user thought the page was ready.
Architectural Diagram (SSR):
3. Static Site Generation (SSG): Build-Time Prerendering
Static Site Generation (SSG) takes the concept of pre-rendering a step further. Instead of rendering pages on the server for each request, SSG renders all possible pages at build time. These pre-generated HTML, CSS, and JavaScript files are then deployed to a content delivery network (CDN). When a user requests a page, the CDN simply serves the static file, resulting in incredibly fast load times.
How it Works:
- Build Time: During the build process (e.g., in your CI/CD pipeline), the Angular application is executed for each defined route.
- Angular generates a complete HTML file for each route.
- These static HTML, CSS, and JavaScript files are deployed to a CDN.
- Runtime: User requests a URL.
- CDN serves the pre-generated HTML file directly to the browser.
- Browser instantly displays the content.
- Client-side Angular then hydrates the page, similar to SSR.
Why Choose SSG?
- Extreme Performance: Pages are served instantly from a CDN, leading to the fastest possible load times and excellent Core Web Vitals scores.
- Excellent SEO: Search engines love static HTML.
- Highly Scalable & Low Cost: CDNs are designed for massive scale and are generally cheaper than dynamic servers. No server-side rendering computation per request.
- Enhanced Security: Less attack surface since there’s no dynamic server-side code execution on request.
Downsides & Production Failure Scenario: “The Stale Content Surprise”
- Not for Highly Dynamic Content: SSG is best for content that doesn’t change frequently or isn’t highly personalized per user (e.g., marketing pages, blogs, documentation). For real-time data or user-specific dashboards, SSG alone is insufficient.
- Rebuild Times: Any content update requires a full rebuild and redeployment of the static site. For very large sites with frequent updates, this can lead to long build times.
- Client-Side Data Fetching: If a static page needs some dynamic data, it still has to fetch it client-side after hydration, which might cause a brief content shift.
Failure Scenario: The Stale Content Surprise Your marketing team updates a crucial product price on your e-commerce site’s public product page. However, because the page is generated statically, and the CI/CD pipeline for rebuilding and redeploying the site fails or is overlooked, the old price remains visible to users for hours or even days. Customers see one price, proceed to checkout, and find a different (updated) price, leading to confusion, distrust, and potentially lost sales.
Architectural Diagram (SSG):
4. Hybrid Rendering: The Best of All Worlds
Modern Angular (especially with @angular/ssr and built-in hydration) truly shines in its ability to support hybrid rendering. This approach allows you to strategically combine SPA, SSR, and SSG within a single application, optimizing each part for its specific needs. For example, your marketing pages might be SSG for maximum performance and SEO, your user dashboard might be an SPA (or SSR for initial load), and public dynamic pages might use SSR.
How it Works:
The application’s routing logic or a proxy/gateway decides which rendering strategy to apply based on the requested route or component.
- Public, unchanging content (e.g.,
/about,/blog): Prerendered at build time (SSG). - Public, dynamic content (e.g.,
/product/:id): Server-side rendered on demand (SSR). - Authenticated, highly interactive dashboards (e.g.,
/dashboard): Client-side rendered after initial authentication (SPA).
Angular’s @angular/ssr package and its prerender command (which leverages Angular Universal internally) provide the tools to achieve this flexibility.
Why Choose Hybrid Rendering?
- Optimal Performance and SEO: Apply the most performant strategy where it matters most.
- Maximum Flexibility: Tailor rendering to specific content types and user journeys.
- Scalability: Leverage CDNs for static content while reserving server resources for dynamic SSR.
Downsides & Production Failure Scenario: “The Configuration Maze”
- Increased Complexity: Managing different rendering strategies across various routes or components requires careful planning and configuration.
- Debugging Challenges: Issues can be harder to diagnose when different parts of the app behave differently due to their rendering method.
- Inconsistent User Experience (if not carefully managed): A sudden shift from an instantly loaded SSG page to a slow-loading SPA section can be jarring.
Failure Scenario: The Configuration Maze Your enterprise portal uses hybrid rendering. The public login page is SSG, the user dashboard is an SPA, and an administrative reporting tool uses SSR. A new developer joins the team and misconfigures a new reporting route to be SSG, even though it relies on real-time, personalized data. Now, when an admin tries to view reports, they either see stale data (if prerendered) or encounter errors because the client-side data fetching logic expects a dynamic server environment that isn’t present in the static files. Diagnosing this involves navigating complex build processes and server configurations.
Architectural Diagram (Hybrid - Conceptual):
Step-by-Step Implementation: Building a Hybrid Angular App
Let’s get hands-on and see how to set up an Angular application that leverages SSR and hydration. We’ll start with a fresh Angular project, add Universal, and demonstrate how content is rendered server-side and then hydrated client-side.
1. Project Setup (Angular v17+ Standalone)
First, let’s ensure we have the latest Angular CLI and create a new project. As of 2026, standalone components are the default and recommended approach.
# Make sure you have the latest Angular CLI globally installed
npm install -g @angular/cli@latest
# Create a new Angular project with standalone components and routing
# Using Angular CLI v17+
ng new my-hybrid-angular-app --standalone --routing --style=css
cd my-hybrid-angular-app
Explanation: We’re creating a brand-new Angular application. The --standalone flag ensures that our components, directives, and pipes are self-contained, requiring fewer NgModule boilerplate. --routing sets up the basic routing module, and --style=css specifies our preferred stylesheet language.
2. Adding Angular Universal (SSR/SSG Capabilities)
Now, let’s inject the power of Server-Side Rendering and Static Site Generation into our app using the official @angular/ssr package.
ng add @angular/ssr@latest
Explanation: This single command does a lot of heavy lifting:
- It installs the
@angular/ssrpackage and its dependencies. - It creates
src/main.server.tsas the entry point for your server-side application. - It adds
server.ts(an Express.js server) to handle incoming requests and serve your Angular app. - It updates your
angular.jsonwith new configurations for building and serving an SSR application ("serve-ssr","prerender"). - Crucially, it adds
provideClientHydration()to yoursrc/app/app.config.ts, enabling Angular’s built-in hydration mechanism.
3. Understanding the Configuration Changes
Take a moment to peek at the files ng add @angular/ssr modified or created:
angular.json: You’ll find new configurations underarchitectforserverandprerendertargets. These define how your server-side bundle is built and how static pages are generated.src/main.server.ts: This is the entry point for your Angular application when it runs on the server.server.ts: This file sets up an Express.js server that listens for HTTP requests. It usesrenderApplication(from@angular/platform-server) to render your Angular app to HTML on the server and then sends that HTML back to the browser.src/app/app.config.ts: This is whereprovideClientHydration()was added.// src/app/app.config.ts import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core'; import { provideRouter } from '@angular/router'; import { provideClientHydration } from '@angular/platform-browser'; // <-- This is key! import { routes } from './app.routes'; export const appConfig: ApplicationConfig = { providers: [ provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes), provideClientHydration() // Enables Angular's built-in hydration ] };Explanation:
provideClientHydration()is a function that provides the necessary services for Angular to perform hydration. When hydration is enabled, Angular intelligently reuses the DOM nodes that were rendered by the server instead of destroying and re-creating them. It then attaches event listeners and client-side state, making the application interactive.
4. Running the SSR Application
Now, let’s see our SSR app in action!
npm run dev:ssr
Explanation: This command first builds both your client-side (browser) and server-side bundles, then starts the Express.js server (from server.ts) which will serve your pre-rendered Angular application.
- Open your browser and navigate to
http://localhost:4200. - Challenge: Open your browser’s developer tools (usually F12 or Cmd+Option+I), go to the “Network” tab, and refresh the page.
- What to observe: Look at the initial HTML document request (usually the first one, named
localhostor similar). In its “Response” tab, you should see the full HTML content of your Angular application, including text and elements, not just<app-root>. This confirms that the content was rendered on the server before being sent to your browser!
5. Demonstrating Hydration and Server/Client Distinction
Let’s create a simple component to clearly illustrate how SSR works with hydration and how to handle server-specific vs. client-specific logic.
Generate a new
HomeComponent:ng generate component home --standaloneUpdate
src/app/home/home.component.ts:import { Component, OnInit, OnDestroy, PLATFORM_ID, Inject } from '@angular/core'; import { CommonModule, isPlatformBrowser } from '@angular/common'; // Important for platform detection @Component({ selector: 'app-home', standalone: true, imports: [CommonModule], // Needed for DatePipe template: ` <h1>Welcome to Our Hybrid Angular App!</h1> <p>This content was initially rendered on the <strong>{{ renderLocation }}</strong>.</p> <p>Current time: <strong>{{ currentTime | date:'mediumTime' }}</strong></p> <button (click)="incrementCounter()">Click Me!</button> <p>You clicked {{ clickCount }} times.</p> <p *ngIf="isBrowser">This paragraph only appears on the client!</p> `, styles: [` :host { display: block; padding: 20px; text-align: center; } button { padding: 10px 20px; font-size: 1.2em; cursor: pointer; margin-top: 15px; background-color: #007bff; color: white; border: none; border-radius: 5px; } button:hover { background-color: #0056b3; } strong { color: #007bff; } `] }) export class HomeComponent implements OnInit, OnDestroy { renderLocation: string = 'server'; currentTime: Date = new Date(); clickCount: number = 0; isBrowser: boolean; private intervalId: any; // Inject PLATFORM_ID to determine where the code is running constructor(@Inject(PLATFORM_ID) private platformId: Object) { this.isBrowser = isPlatformBrowser(this.platformId); if (this.isBrowser) { this.renderLocation = 'client'; // Update if running on client // Only set up client-side interval if in browser this.intervalId = setInterval(() => { this.currentTime = new Date(); }, 1000); } } ngOnInit(): void { console.log(`HomeComponent initialized on ${this.renderLocation}`); } ngOnDestroy(): void { if (this.isBrowser && this.intervalId) { clearInterval(this.intervalId); } } incrementCounter(): void { this.clickCount++; } }Explanation:
- We inject
PLATFORM_IDand useisPlatformBrowser()from@angular/commonto determine if our code is running in a browser environment. This is the correct and robust way to handle environment-specific logic in universal Angular apps. renderLocationwill initially be ‘server’ in the server-rendered HTML. On the client, ifisPlatformBrowseris true, it updates to ‘client’.- The
currentTimeis initially set on the server, and then ansetInterval(only running on the client) continuously updates it, demonstrating client-side interactivity after hydration. - The
clickCountbutton clearly shows client-side interactivity. - The
*ngIf="isBrowser"directive ensures the paragraph only renders on the client, preventing hydration mismatches for browser-specific content.
- We inject
Update
src/app/app.routes.tsto useHomeComponent:// src/app/app.routes.ts import { Routes } from '@angular/router'; import { HomeComponent } from './home/home.component'; // Import HomeComponent export const routes: Routes = [ { path: '', component: HomeComponent } // Set HomeComponent as the default route ];Ensure your
AppComponentuses<router-outlet>if it’s not already:// src/app/app.component.ts (check this file, usually it's set up correctly) import { Component } from '@angular/core'; import { RouterOutlet } from '@angular/router'; @Component({ selector: 'app-root', standalone: true, imports: [RouterOutlet], template: ` <main> <router-outlet></router-outlet> </main> `, styles: [] }) export class AppComponent { title = 'my-hybrid-angular-app'; }Restart your SSR server:
npm run dev:ssrObserve Carefully:
- View Page Source (Ctrl+U or Cmd+Option+U): You should see the full HTML, including
<h1>Welcome to Our Hybrid Angular App!</h1>,This content was initially rendered on the <strong>server</strong>, and an initial timestamp. The paragraphThis paragraph only appears on the client!should not be present in the initial source. This is proof of SSR. - In the Browser: The page loads quickly. The
Current timeshould immediately start updating every second. The “Click Me!” button should be interactive right away, incrementing the count. The paragraph “This paragraph only appears on the client!” should now be visible. - Developer Console: Look for any hydration warnings (e.g., “NG0500: Angular hydration has detected that the application rendered a different DOM structure”). If you’ve followed the steps, you shouldn’t see any, demonstrating successful hydration. If you were to temporarily remove
provideClientHydration()fromapp.config.ts, you might observe a brief flicker or re-render as the client-side app re-initializes the DOM.
- View Page Source (Ctrl+U or Cmd+Option+U): You should see the full HTML, including
6. Static Site Generation (SSG) with Prerendering
For pages that are truly static, like an “About Us” page or a blog, we can pre-render them at build time, deploying only static HTML files.
- Challenge: Create a new
AboutComponentand add a route for/about. Then, configure your project to prerender this route.Generate
AboutComponent:ng generate component about --standaloneUpdate
src/app/about/about.component.tswith some static content:import { Component } from '@angular/core'; @Component({ selector: 'app-about', standalone: true, imports: [], template: ` <div class="about-container"> <h2>About Our Awesome Company</h2> <p>We are dedicated to building amazing web applications with Angular!</p> <p>This page is perfect for static site generation as its content rarely changes.</p> <a routerLink="/">Go Home</a> </div> `, styles: [` .about-container { padding: 30px; text-align: center; background-color: #f8f9fa; border-radius: 8px; margin: 20px auto; max-width: 600px; box-shadow: 0 4px 8px rgba(0,0,0,0.1); } h2 { color: #343a40; margin-bottom: 20px; } p { color: #6c757d; line-height: 1.6; } a { color: #007bff; text-decoration: none; font-weight: bold; margin-top: 15px; display: inline-block; } a:hover { text-decoration: underline; } `] }) export class AboutComponent { }Add the route to
src/app/app.routes.ts:// src/app/app.routes.ts import { Routes } from '@angular/router'; import { HomeComponent } from './home/home.component'; import { AboutComponent } from './about/about.component'; // Import AboutComponent export const routes: Routes = [ { path: '', component: HomeComponent }, { path: 'about', component: AboutComponent } // Add the about route ];Configure Prerendering: The
ng add @angular/ssrcommand already added aprerenderscript to yourpackage.json.- Open
package.json. You should see a script like:"prerender": "ng run my-hybrid-angular-app:prerender" - This script will automatically detect and prerender all routes configured in your
app.routes.ts.
- Open
Run the full build and prerender process:
npm run buildExplanation: The
buildscript will first compile your Angular app for the browser and server. Then, theprerenderstep will run, navigating through your defined routes and generating static HTML files for them.What to observe: After the build completes, navigate to the
dist/my-hybrid-angular-app/browserdirectory. You should now find:index.html(for the root route, prerendered)- An
about/directory containingindex.html(for your/aboutroute, also prerendered). - You can serve these files using a simple static server (e.g.,
npx serve dist/my-hybrid-angular-app/browser) and inspect their source to confirm they contain the full HTML content.
This demonstrates the power of hybrid rendering: dynamic interactive pages (like your home page) can benefit from SSR, while static content (like your about page) can be pre-rendered for ultimate performance and served from a CDN.
Common Pitfalls & Troubleshooting
Even with Angular’s streamlined approach, universal rendering can introduce complexities. Here are some common issues and how to tackle them:
1. Hydration Mismatches
- Pitfall: This is the most frequent issue. Angular’s hydration mechanism expects the server-rendered HTML to perfectly match the HTML generated by the client-side application. If there’s a discrepancy, Angular logs a warning (e.g.,
NG0500: Angular hydration has detected that the application rendered a different DOM structure...) and might fall back to re-rendering the entire component, negating hydration’s benefits. Common causes include:- Direct DOM manipulation using
documentornativeElementinngOnInit(which runs on both server and client). - Using browser-specific APIs (
window,localStorage) that modify content during server-side rendering. - Differences in data fetched on the server vs. client during the initial render.
- Direct DOM manipulation using
- Troubleshooting: Always check your browser’s developer console for hydration warnings. They are usually very descriptive, pointing to the exact HTML elements that mismatched.
- Solution:
- Guard browser-specific code: Use
isPlatformBrowser(this.platformId)(as shown in ourHomeComponentexample) to ensure code interacting withwindow,document, orlocalStorageonly runs in the browser. - Avoid direct DOM manipulation: Prefer Angular’s templating and data binding for UI updates. If direct manipulation is unavoidable, ensure it’s guarded by
isPlatformBrowser. - Consistent data: Ensure that any data used to render the initial HTML is the same on both the server and client.
- Guard browser-specific code: Use
2. Browser-Specific APIs on the Server
- Pitfall: Your server-side Angular application runs in a Node.js environment, which doesn’t have browser globals like
window,document,localStorage,sessionStorage, etc. Trying to access these directly in your component code (even if it’s not directly related to rendering) will cause aReferenceError: window is not definedor similar errors during the server-side build or runtime. - Troubleshooting: Your
npm run dev:ssrornpm run buildcommand will fail with aReferenceError. - Solution:
- Use
isPlatformBrowser(): This is the primary solution. Wrap any code that accesses browser-specific APIs within anif (isPlatformBrowser(this.platformId))block. - Abstract browser APIs: Create services that abstract away browser-specific functionality (e.g., a
StorageServicethat useslocalStorageon the client and a no-op or mock implementation on the server). - Inject
DOCUMENT: For DOM manipulation, injectDOCUMENTfrom@angular/commoninstead of using globaldocument.
- Use
3. Performance Bottlenecks in SSR
- Pitfall: While SSR improves FCP, a slow server-side rendering process can increase your Time To First Byte (TTFB). If your server-side Angular app is making many slow API calls, complex computations, or waiting for database queries, the user will still wait longer for the initial HTML response.
- Troubleshooting: Monitor your server’s CPU and memory usage during SSR. Use tools like Lighthouse or WebPageTest to analyze your TTFB. Profile the Node.js process running your Angular Universal app.
- Solution:
- Optimize data fetching: Parallelize API calls, implement caching (e.g., Redis) for frequently accessed data, and ensure your backend APIs are performant.
- Edge caching: Use a CDN or a reverse proxy like Nginx to cache server-rendered HTML for static or semi-static pages, reducing the load on your Node.js server.
- Minimize server-side logic: Avoid unnecessary complex calculations on the server if they can be deferred to the client without impacting FCP.
Summary
Phew! We’ve covered a lot of ground on how Angular applications come to life in the browser. Here are the key takeaways:
- Rendering Strategy is a Core Architectural Decision: It directly impacts performance, SEO, user experience, and operational costs.
- Single Page Application (SPA): Client-side rendering, great for rich, interactive apps, but can suffer from initial blank screens and SEO challenges.
- Server-Side Rendering (SSR): Server pre-renders initial HTML, leading to faster First Contentful Paint and better SEO. Angular Universal is the tool.
- Static Site Generation (SSG): Pages rendered at build time, offering extreme performance, scalability, and security for static content. Achieved with Angular Universal’s prerendering.
- Hybrid Rendering: The modern approach, combining SPA, SSR, and SSG to optimize different parts of your application for specific needs. Angular’s
@angular/ssrand built-in hydration make this powerful combination seamless. - Hydration is Key: This process allows client-side Angular to efficiently take over from server-rendered HTML, attaching interactivity without re-rendering, crucial for a smooth user experience.
- Guard Browser-Specific Code: Always use
isPlatformBrowser()to conditionally execute code that relies on browser globals (window,document,localStorage) to prevent errors in SSR environments and avoid hydration mismatches.
Understanding these rendering strategies empowers you to make informed decisions about how your Angular applications deliver content, ensuring they are not only functional but also performant, discoverable, and user-friendly.
What’s Next?
Now that we understand how to deliver our Angular application effectively, it’s time to think about how to scale it! In the next chapter, we’ll dive into Microfrontends and Module Federation, exploring advanced techniques to break down monolithic frontends into independently deployable units, enhancing maintainability and enabling large teams to work more efficiently.
References
- Angular Official Documentation: Server-side rendering (SSR) and prerendering
- Angular Official Documentation: Hydration
- MDN Web Docs: Client-side rendering vs Server-side rendering
- Angular CLI GitHub Repository (for
ng add @angular/ssrcontext)
This page is AI-assisted and reviewed. It references official documentation and recognized resources where relevant.