DEV Community

Martin Choraine for Zenika

Posted on • Edited on

7

Angular Universal with Standalone Component

With the arrival of Standalone Component with Angular 15, it is now possible to do without @NgModules entirely. This opens the door to new possibilities.

It is now possible to bootstrap an Angular application by providing an entry point component with a list of providers in the main.ts :

bootstrapApplication(AppComponent, {
  providers: [
    provideAnimations(),
    provideRouter(routes)
  ]
})
Enter fullscreen mode Exit fullscreen mode

However, with this new approach, it is not yet possible to simply take advantage of the server side rendering (SSR) with Angular Universal because the function ngExpressEngine only takes a module parameter and not a component:

import express from 'express';
import { ngExpressEngine } from '@nguniversal/express-engine';

const app = express();

// Set the engine
app.engine(
  'html',
  // Bootstrap and render NgModule with express adapter for `@angular/platform-server`
  ngExpressEngine({
    // Take a module but we would like to provide component
    bootstrap: ServerAppModule
  }),
);

app.set('view engine', 'html');

app.get('/**/*', (req: Request, res: Response) => {
  res.render('../dist/index', {
    req,
    res,
  });
});
Enter fullscreen mode Exit fullscreen mode

On the other hand it is possible to use manually the render function provided by @angular/platform-server.
This forces us to redo the work done by Angular Universal inside ngExpressEngine but it's the only possibility while waiting for the support of standalone component :

import express from 'express';
import type { Request, Response } from 'express';
import * as fs from 'fs';
import { renderApplication } from '@angular/platform-server'

const app = express();

app.engine('html', async (path, options, callback) => {
    const document = fs.readFileSync(path, 'utf-8')
    const { req } = { ...options } as {req: Request, res: Response};

    // Bootstrap and render a Standalone Component 
    const html = await renderApplication(AppComponent, {
      appId: 'server-app',
      document: document,
      url: `${req.baseUrl}${req.url}`,
      providers: [
        provideRouter(routes),
      ]
    });
    callback(null, html)
});
app.set('view engine', 'html');

app.get('/**/*', (req: Request, res: Response) => {
  res.render('../dist/index', {
    req,
    res,
  });
});
Enter fullscreen mode Exit fullscreen mode

Thanks to the function renderApplication, it is possible to bootstrap an Angular component and render it on the server side while waiting for the full support of Standalone Component in Angular Universal with the provided function ngExpressEngine.

Heroku

This site is built on Heroku

Join the ranks of developers at Salesforce, Airbase, DEV, and more who deploy their mission critical applications on Heroku. Sign up today and launch your first app!

Get Started

Top comments (3)

Collapse
 
zuhairkareem profile image
zuhairkareem

It is now implemented in Angular v16 according to this (
github.com/angular/universal/pull/...)

ref: reddit.com/r/angular/comments/zqko...

Collapse
 
vytautaspranskunas profile image
Vytautas Pranskunas

Would you mid sharing whole example?

Collapse
 
sabihope profile image
sabihope

Do we need to render each standalone component?

Cloudinary image

Optimize, customize, deliver, manage and analyze your images.

Remove background in all your web images at the same time, use outpainting to expand images with matching content, remove objects via open-set object detection and fill, recolor, crop, resize... Discover these and hundreds more ways to manage your web images and videos on a scale.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay