Soumaya Erradi
Posted on August 4, 2024
Server Side Rendering
Server-Side Rendering (SSR) has become pivotal in frontend development, reflecting a trend toward optimizing web applications for performance, accessibility, and user experience. SSR's ability to deliver pre-rendered HTML pages from the server improves initial load times, crucial for users on slower networks or devices. This enhances user experience and reduces bounce rates. SSR also boosts SEO by making content easier for search engines to crawl and index, leading to better visibility and higher rankings.
By ensuring a fast, reliable, and consistent user experience across different devices and network conditions, SSR improves engagement and retention. It also makes the web more inclusive, particularly for users with limited JavaScript support. SSR optimizes resource usage by shifting rendering from the client to the server, enhancing performance and allowing efficient resource management. Server-side rendered pages can be easily cached, improving load times and reducing server load.
SSR enhances security by processing sensitive data on the server, mitigating risks associated with client-side rendering. This server-side processing helps prevent attacks that exploit client-side vulnerabilities. Despite evolving web standards and user expectations, SSR remains essential for delivering fast, seamless, and secure web experiences, ensuring content is delivered quickly and reliably across all devices and network conditions.
Hystory of SSR and Angular
In the beginning, web development was heavily dependent on server-side technologies such as PHP, Java, Ruby, and ASP.NET to render content. Server-side rendering (SSR) was the primary focus in this era, as client-side rendering was not common.
However, around a decade later, the trend shifted dramatically towards client-side rendering. Frameworks and libraries for single-page applications (SPAs) like AngularJS became popular, and SSR seemed to be a thing of the past. Most of the rendering tasks on the client side were managed by JavaScript applications during this period.
Angular, launched in 2010 as AngularJS, was created in this SPA-centric era. Although the Angular team mentioned the initial exploration of SSR capabilities, the team ultimately gave up these efforts. They believed that enhancing client-side performance could address the traditional needs of SSR, particularly SEO and initial load performance.
Despite initial skepticism, the importance of SSR reappeared. SSR was introduced through Angular Universal especially to its importance for performance and SEO.
Angular Universal
Jeff Whelpley developed Angular Universal to enable server-side rendering. Angular applications can improve initial load times, SEO, and overall performance by rendering on the server and sending fully rendered pages to the client.
To implement SSR in an Angular application using Angular Universal, you follow these steps:
Install Angular Universal:
ng add @nguniversal/express-engine
This command sets up Angular Universal with an Express server.
The Angular CLI creates necessary files, including main.server.ts
and server.ts
.
main.server.ts:
import { enableProdMode } from '@angular/core';
import { environment } from './environments/environment';
import { AppServerModule } from './app/app.server.module';
import { ngExpressEngine } from '@nguniversal/express-engine';
import { provideClientHydration } from '@angular/platform-server';
if (environment.production) {
enableProdMode();
}
export { AppServerModule } from './app/app.server.module';
export { renderModuleFactory } from '@angular/platform-server';
server.ts:
import 'zone.js/node';
import { ngExpressEngine } from '@nguniversal/express-engine';
import * as express from 'express';
import { join } from 'path';
import { AppServerModule } from './src/main.server';
import { APP_BASE_HREF } from '@angular/common';
import { existsSync } from 'fs';
export function app(): express.Express {
const server = express();
const distFolder = join(process.cwd(), 'dist/your-project-name/browser');
const indexHtml = existsSync(join(distFolder, 'index.original.html')) ? 'index.original.html' : 'index';
server.engine('html', ngExpressEngine({
bootstrap: AppServerModule,
}));
server.set('view engine', 'html');
server.set('views', distFolder);
server.get('*.*', express.static(distFolder, {
maxAge: '1y'
}));
server.get('*', (req, res) => {
res.render(indexHtml, { req });
});
return server;
}
function run(): void {
const port = process.env.PORT || 4000;
const server = app();
server.listen(port, () => {
console.log(`Node Express server listening on http://localhost:${port}`);
});
}
declare const __non_webpack_require__: NodeRequire;
const mainModule = __non_webpack_require__.main;
const moduleFilename = mainModule && mainModule.filename || '';
if (moduleFilename === __filename || moduleFilename.includes('iisnode')) {
run();
}
export * from './src/main.server';
Create app.server.module.ts
to include server-specific modules.
import { NgModule } from '@angular/core';
import { ServerModule } from '@angular/platform-server';
import { AppModule } from './app.module';
import { AppComponent } from './app.component';
@NgModule({
imports: [
AppModule,
ServerModule,
],
bootstrap: [AppComponent],
})
export class AppServerModule {}
Hydration
SSR has been greatly improved with the release of Angular 16, particularly with hydration. When SSR was used by Angular applications, the server would send an HTML page that was fully rendered to the client. This server-rendered HTML would be destroyed by Angular and re-rendered on the client side, resulting in performance inefficiencies.
With the introduction of hydration in Angular 16, the client can reuse the HTML generated by the server instead of discarding it and generating it again. By reducing the redundant rendering process, this improvement enhances the performance and speed of Angular applications.
It's easy to implement hydration in Angular 16. The hydration can be enabled for developers by providing a specific configuration in their Angular application.
Configuration: In your Angular application, add the provideClientHydration
provider to enable hydration.
import { provideClientHydration } from '@angular/platform-server';
providers: [
provideClientHydration(),
// other providers
]
Angular 17
The capabilities of Server-Side Rendering (SSR) and client-side hydration have been further enhanced by the Angular team with the release of Angular 17. These updates reflect a continued commitment to optimizing performance, improving developer experience, and ensuring that Angular remains a robust framework for modern web applications.
The stabilization and improvement of hydration is one of the standout features of Angular 17. In previous versions, while SSR and basic hydration were supported, they were not fully optimized for production use. Angular 17 has resolved these issues, ensuring that hydration is stable and reliable for production environments.
Hydration in Angular 17 ensures that the pre-rendered HTML from the server is not discarded when it reaches the client. Instead, the client-side Angular application can reuse this HTML by attaching event handlers and rehydrating dynamic content without re-rendering everything.
Angular 17 has also simplified the process of setting up SSR. Previously, developers needed to install and configure Angular Universal separately. Angular 17 has brought Angular Universal directly into the Angular CLI, simplifying the setup process. SSR can be enabled by developers using a single command, which makes it more accessible and easier to implement.
To create an SSR-enabled application from the start, developers can use the following command:
ng new my-app --ssr
If SSR was not enabled initially, it can be added to an existing project with:
ng add @angular/ssr
These commands configure the necessary dependencies and files, such as server.ts
and main.server.ts
, automatically, reducing the manual configuration required in previous versions.
Angular 18+
Angular 18 introduces significant improvements in Server-Side Rendering (SSR) and hydration, focusing on performance optimization and enhanced developer experience.
-
Internationalization Support:
- Angular 18 now includes developer preview support for internationalization within SSR, addressing previous issues. Developers can enable this feature using
withI18nSupport
in theprovideClientHydration
provider.
- Angular 18 now includes developer preview support for internationalization within SSR, addressing previous issues. Developers can enable this feature using
-
Event Replay:
- The new event replay feature records user interactions, such as clicks and double-clicks, during the hydration phase and replays them once hydration is complete. This ensures a smoother user experience and can be enabled with
withEventReplay
in theprovideClientHydration
provider.
- The new event replay feature records user interactions, such as clicks and double-clicks, during the hydration phase and replays them once hydration is complete. This ensures a smoother user experience and can be enabled with
-
Angular Material Improvements:
- Initial steps towards integrating Angular Material components with SSR are included in this release. Although still in developer preview, these features show promise for full support in future updates.
Conclusion
Angular 17 marked significant progress in SSR and hydration, integrating Angular Universal into the core CLI and stabilizing hydration. Looking forward, Angular 18+ will continue to enhance these capabilities, focusing on improved performance, developer experience, and expanded framework features. These advancements ensure Angular remains a leading framework for building dynamic, high-performance web applications, meeting the evolving needs of developers and users alike.
Posted on August 4, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.