DEV Community

Cover image for Pre-rendering frontend with Angular Universal & Firebase Hosting
Quokka Labs for Quokka Labs

Posted on • Edited on

Pre-rendering frontend with Angular Universal & Firebase Hosting

Nowadays, if you want to build a front-end application, Angular comes first in mind. This frontend development framework resembles the features and accessibility of the single-page application. Angular is best known for client-side rendering(frontend development), but it stretches the functionalities on the server side. The Angular Universal responds to this part.

How does Angular Universal differ from Angular?

One major difference between Angular and Angular Universal is their execution environment. Angular manages the js download and rendering and prepares the dynamics at the browser first, whereas Angular Universal serves on the server side.

What is the need for Angular Universal?

When we plan an angular based project for rendering, first, JS is downloaded on the browser side; then, the rendering begins inside the browser. After that, the user for further actions. We can't predict things at rapid speed, but things get delayed by poor connectivity. JS files take more time to download and render. Nothing will appear on the webpage.

Angular Universal emerged as an exclusive and exceptional tool to take care of such issues. However, you don’t have any access to make angular script changes. But it can offer pre-rendering on the server side. At the same time, it is waiting for the status of the JS download. Both processes will run subsequently and seamlessly. This action will reduce the load duration at the browser and deliver a fast response.

With Angular Universal support or mutual integration of Angular Firebase Hosting, users can interact with the webpage despite poor connectivity.

Also, Get to know the accessibility and practices of firebase remote configuration.

Access the blog:

Angular Universal has comforted three most interesting things:

  • Performance Enhancement for mobile devices/ low-powered devices
  • SEO Support
  • Rendering in low connectivity

Angular Universal and Firebase Hosting- perfect for server-side rendering

Integration of Angular Firebase hosting ecosystem enables faster dynamic content delivery to angular based frontend development. To access the features of Angular Universal, hit this command in the terminal.

ng add @nguniversal/express-engine –clientProject projectname

It will enable the server-side application rendering accessibilities.

The angular.json file contains the project name. You can get all the pre-rendering stuff from here. If you are using an older version of Angular 8, you may lack some accessibility. To resolve any inconvenience, please import ModuleMapLoader. You can access the site from the import section as app.server.module.ts.

Hit this command, and it will appear on the screen:
npm install –save @nguniversal/module-map-ngfactory-loader

You can save your efforts importing this module if you have angular 9 or above support.

This thing is great from a user experience point of view. Users won’t be disappointed by slow loading issues when interacting with the application.

Server-side and browser-side methods are different. It will impact application production. We can swap the methods to align the requirements. You can check the type of platform to avoid the application build.

Use @angular/ common method and inspect the platform type.

If you are building an angular-based application, then you need a dynamic host. You could only manage the full server-side rendering with a Node Js server.

To initiate the angular application build, hit this command:
npm run build:ssr

Then, install and setup the Node.js server and hit the command:
npm run serve:ssr

With these one-liner commands, you can manage the pre-rendering of essential dynamics.

The process to Setup Firebase Hosting for Angular Universal

To streamline the instant rendering for the first page following the angular universal, we also need to integrate this angular firebase hosting.

Firebase-tools installation

Firebase also has a suite of resources that need to be installed for seamless integration. Hut the command:
npm i -g firebase-tools

Platform server installation

Next, you need to access the platform server accessibilities for that, copy this command and hit on the terminal:
npm i --save @angular/platform-server

Now access app.module.ts to make changes BrowserModule

imports: [
    BrowserModule.withServerTransition({ 
      appId: 'project_name' 
    }),
    AppRoutingModule
  ],
`
"projects": {
    "project_name": {
      "root": "",
Enter fullscreen mode Exit fullscreen mode

Access src/app and create app.server.module.ts and use this inside

import { NgModule } from '@angular/core';
import { ServerModule } from '@angular/platform-server';
import { AppModule } from './app.module';
import { AppComponent } from './app.component';

@NgModule({
    imports: [
        ServerModule,
        AppModule
    ],
    bootstrap: [AppComponent]
})
export class AppServerModule { }
Enter fullscreen mode Exit fullscreen mode

Now create another file to src naming as main.server.ts

export { AppServerModule } from './app/app.server.module';

We need to add a tsconfig.server.json. It’s a file.

{
    "extends": "../tsconfig.json",
    "compilerOptions": {
      "outDir": "../out-tsc/app",
      "baseUrl": ".",
      "module": "commonjs",
      "types": []
    },
    "exclude": [
      "test.ts",
      "**/*.spec.ts"
    ],
    "angularCompilerOptions": {
      "entryModule": "app/app.server.module#AppServerModule"
    }
}
Enter fullscreen mode Exit fullscreen mode

Do customization to angular.json

Go to architect and include server after lint

"lint" : {
    ...
}, "server": {
      "builder": "@angular-devkit/build-angular:server",
      "options": {
        "outputPath": "functions/dist/server",
        "main": "src/main.server.ts",
        "tsConfig": "src/tsconfig.server.json"
      }
    }
Enter fullscreen mode Exit fullscreen mode

Follow the path for the additional changes: Access build, then options then outputPath

"build": {
          "builder": "@angular-devkit/build-angular:browser",
          "options": {
            "outputPath": "functions/dist/browser",
Enter fullscreen mode Exit fullscreen mode

Now initialize the production for the browser and server.

ng build --prod
ng run project_name:server

Initiate the setup for firebase

firebase init

  • Do further important things: functions, hosting.
  • Also, look for the firebase console and the project you want to work
  • Then add Js cloud functions
  • ESLint: No
  • Disable Dependency installation for now
  • Set the status public for the public directory
  • Enable single-page app configuration

Access the Function Directory and eliminate the scripts block, go to the root directory and access angular project package.json, and add the dependencies here. Remember that your project's version and dependencies vary, so please check.

{
  "name": "functions",
  "description": "Cloud Functions for Firebase",
  "dependencies": {
    "firebase-admin": "~6.0.0",
    "firebase-functions": "^2.1.0",
    "@angular/animations": "~7.1.0",
    "@angular/common": "~7.1.0",
    "@angular/compiler": "~7.1.0",
    "@angular/core": "~7.1.0",
    "@angular/forms": "~7.1.0",
    "@angular/http": "^7.1.4",
    "@angular/platform-browser": "~7.1.0",
    "@angular/platform-browser-dynamic": "~7.1.0",
    "@angular/platform-server": "^7.1.4",
    "@angular/router": "~7.1.0",
    "core-js": "^2.5.4",
    "rxjs": "~6.3.3",
    "tslib": "^1.9.0",
    "zone.js": "~0.8.26"
  },
  "private": true
}
Enter fullscreen mode Exit fullscreen mode

Access the Angular project’s root directory for function installation and execute the below command:

npm --prefix functions install

Access the functions directory and look for index.js. Remove the existing code and add the below piece of code:

require('zone.js/dist/zone-node');

const functions = require('firebase-functions');
const express = require('express');
const path = require('path');
const { enableProdMode } = require('@angular/core');
const { renderModuleFactory } = require('@angular/platform-server');

const { AppServerModuleNgFactory } = require('./dist/server/main');

enableProdMode();

const index = require('fs')
  .readFileSync(path.resolve(__dirname, './dist/browser/index.html'), 'utf8')
  .toString();

let app = express();

app.get('**', function(req, res) {
  renderModuleFactory(AppServerModuleNgFactory, {
    url: req.path,
    document: index
  }).then(html => res.status(200).send(html));
});

exports.ssr = functions.https.onRequest(app);
Enter fullscreen mode Exit fullscreen mode

Access the root directory and look for firebase.json the eliminate the existing content: with this:

{
  "hosting": {
    "public": "public",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "rewrites": [
      {
        "source" : "**/*.@(css|js)",
        "destination": "/index2.html"
      },
      {
        "source": "**",
        "function": "ssr"
      }
    ]
  }
}
Enter fullscreen mode Exit fullscreen mode

Access the public directory and add the build files link, which you can execute from root directory.

cp -a functions/dist/browser/. public/
mv public/index.html public/index2.html

See the demo in the local ecosystem

firebase serve --only functions, hosting

Here the firebase setup is completed!

Angular Universal Integration with Firebase

  • You need Angular Universal Integration or Angular Firebase Hosting to manage the pre-rendering of Angular project dynamic content. ng add @nguniversal/express-engine

You can add as many routes you desire for your project pre-rendering.

{
  "prerender": {
    "builder": "@nguniversal/builders:prerender",
    "options": {
      "routes": [
        "/",
        "ANOTHER_ROUTE",
        "AND_ANOTHER"
      ]
    },
    "configurations": {
      /* ... */
    },
    "defaultConfiguration": "production"
  }
}
Enter fullscreen mode Exit fullscreen mode

You can customize the SSR settings by eliminating the serverTarget and accessing the exclusive pre-rendering.

{
  "deploy": {
    "builder": "@angular/fire:deploy",
    "options": {
      "browserTarget": "app:build:production",
      "serverTarget": "app:server:production",
      "prerenderTarget": "app:prerender:production"
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Here the process of Angular Universal and Firebase Hosting finish. There are many things that are optional as per requirement.

Deploy your single-page application frontend development project seamlessly, managing exclusive pre-rendering access. Furthermore, here is another blog to build a full stack application blending the functionalities of angular with nestjs and next.

Roadmap for Full Stack Application with Angular, NestJS, and Nx

Get to know the best Roadmap for Full Stack Application with Angular, NestJS, and Nx

favicon quokkalabs.hashnode.dev

Hope, this blog would worthy for you in your next projects!

Top comments (1)

Collapse
 
flamel666 profile image
flamel666

Hi, if I wanted to use only prerendering on firebase, is it necessary to enable functions?