Encountered a problem with AngularUniversal prerendering: UnhandledPromiseRejectionWarning: Unable to locate NgModule metadata for 'class{}'

Objective

The task may seem lengthy, but it's straightforward!

Currently, I am utilizing Angular Universal for Server-Side Rendering (SSR) by following a tutorial. The Universal/express-engine has been installed, main.js is generated in the dist/projectname/server directory, and I have created a prerender.js folder in the project root.

Issue

Upon running npm run prerender, the process initiates pre-rendering until encountering the following error:

Error: No NgModule metadata found for 'class{}'

This leads to several UnhandledPromiseRejectionWarning messages and errors throughout the process.

Intended Outcome

I aim to pre-render the HTML of our primary route and save it to a text file.

Attempted Solutions

This approach involved deleting the chained .catch(err...) function of the bootstrap in main.ts, resulting in the same error.

Another method included deleting node-modules and package.json, then running npm install, ng build, ng serve, which also led to the same error.

A different fix advised updating AngularCLI and Webpack, yet the error persisted.

Software Versions

Angular CLI: 10.0.0
Node: 12.16.3
OS: win32 x64

Angular: 10.0.0
... animations, cli, common, compiler, compiler-cli, core, forms
... platform-browser, platform-browser-dynamic, platform-server
... router
Ivy Workspace: <error>

Package                           Version
-----------------------------------------------------------
@angular-devkit/architect         0.900.7
@angular-devkit/build-angular     0.901.9
@angular-devkit/build-optimizer   0.901.9
@angular-devkit/build-webpack     0.901.9
@angular-devkit/core              9.0.7
@angular-devkit/schematics        10.0.0
@angular/cdk                      9.2.4
@angular/fire                     6.0.2
@ngtools/webpack                  9.1.9
@nguniversal/builders             9.1.1
@nguniversal/common               9.1.1
@nguniversal/express-engine       9.1.1
@schematics/angular               10.0.0
@schematics/update                0.1000.0
rxjs                              6.5.5
typescript                        3.9.5
webpack                           4.43.0

Files Involved

  1. prerender.ts
import 'zone.js/dist/zone-node';
import 'reflect-metadata';
import {renderModuleFactory} from '@angular/platform-server';
import {writeFileSync} from 'fs';

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

renderModuleFactory(AppServerModuleNgFactory, {
    document: '<app-root></app-root>',
    url: '/'
})
.then(html => {
    console.log('Pre-rendering successful, saving prerender.html');
    writeFileSync('./prerender.html', html);
})
.catch(error => {
    console.error('Error occurred:', error);
});
  • server.ts
Import statements...

Content of server.ts...
  • main.server.ts
Import statements...

Other code snippets...
  • tsconfig.server.json
Configuration details...
  • angular.json
Project setup details...
  • package.json
Information about npm packages used...

Additional Note

An issue related to Ivy was identified by David. Enabling Ivy in tsconfig.json under compilerOptions > enableIvy resulted in a series of errors related to fontawesome. Previously, disabling Ivy was necessary when integrating fontawesome due to conflicts. Now, finding a solution to make both packages operational together with Ivy enabled is challenging.

Special thanks to David for flagging the Ivy complication.

Answer №1

To solve the initial issue of not finding a NgModule, make sure Ivy is enabled.

If you encounter the error related to an invalid constructor parameter decorator, it may be due to using the outdated package angular-font-awesome which is not compatible with Ivy.

In that case, uninstall the package using the command

npm uninstall angular-font-awesome -S
and stick to the following fortawesome packages:

"@fortawesome/angular-fontawesome": "^0.6.1",
"@fortawesome/fontawesome-free": "^5.13.1",
"@fortawesome/fontawesome-svg-core": "^1.2.29",
"@fortawesome/free-brands-svg-icons": "^5.13.1",
"@fortawesome/free-regular-svg-icons": "^5.13.0",
"@fortawesome/free-solid-svg-icons": "^5.13.1",

Please note: It is unnecessary to create the prerender.ts file as mentioned in a previous comment. Instead, add routes to render in your angular.json and execute ng run prerender.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Ways to ensure that a jQuery function does not run until another one has finished

My JQuery functions are as follows: First Function $(function(){ $(".staffDiv div").hide(); $(".staffDiv img").hover(function(){ $(this).next(".staffDetails").slideToggle("slow").siblings(".staffDetails:visible").slideUp("fast"); $(this) ...

What could be the reason why the keypress event doesn't seem to be functioning properly on

Currently, I am utilizing Angular and the Ionic framework. Here is a snippet of the HTML code that I have written: <div><ion-input type="text" id="phoneNumber" [(ngModel)]="phoneNumber" (keypress)="phoneNumericCh ...

Creating a PDF file from a series of images

I've implemented a function using the jsPDF library to generate a PDF from a list of images. The main task is to add these images to the PDF document. Here is the code snippet: const { allImgs } = useAppContext() const doc = new jsPDF(); const gener ...

Here's a unique version: "Sharing data between functions in the Express GET API within MEAN Stack"

Within my code, I have a function called hsResponse which operates as described below. When I run this function independently, I am able to see the expected body response in the console log. Now, I would like to incorporate this hsResponse function within ...

Guide to sending checkbox data using jQuery AJAX

I am facing an issue with submitting the form below: <form action="/someurl" method="post"> <input type="hidden" name="token" value="7mLw36HxPTlt4gapxLUKWOpe1GsqA0I5"> <input type="checkbox" class="mychoice" name="name" value="appl ...

Tips on saving data in an AngularJS factory after receiving a response from another factory

IFactory.query( function (response) { $scope.type_content = response; $scope.showMenu = true; }, function (response) { $scope.message = "Error: " + response.status + " " + response.statusText; } ); $scope.saving = ...

Running numerous subdomains on a single node.js server

Creating a system with multiple web applications (approximately 3-5 node.js + express applications) on one server with only one domain raises some questions. To segregate each application, subdomains seem to be the way to go. The main question now is how ...

Contrast between the expressions '$(<%= DDL.ID %>) and $('<%= DDL.ID %>')

I spent hours trying to attach an event to a drop-down list with no success. I even sought help in a JavaScript chat room, but couldn't find a solution. However, by randomly attempting the following code: $('<%= ddl.ID %>').bind(&apos ...

Exclude Cancel button solely from pFileUpload

While using pFileUpload, I am able to see all three buttons, however, I do not require the Cancel button. Even though the documentation mentions an attribute called showCancelButton, applying it does not result in any changes. <p-fileUpload name="demo ...

Guide to customizing CSS styles within a div element using TypeScript code in a Leaflet legend

I'm struggling to add a legend to my map using Angular 5 and typescript. I need help with setting CSS styles for the values (grades) that are displayed on the legend. Can someone guide me on where to put the styles? TS: createLegend() { let lege ...

Turn off the serving of static assets in Sails.js

Is there a way to disable serving static assets completely in the configuration settings? I'm wondering if simply adding an empty folder and specifying it in the custom express middleware is the right approach: module.exports = { // Initialize custo ...

What are the steps to correctly implement async await in a standard sequence?

When I press the button onPress={() => Login()} First, I need to obtain a token by using the signInWithKakao function. Secondly, right after acquiring the token, if it is available, I want to dispatch the profile using the kakaoprofile function. Howev ...

What are the steps for integrating bootstrap into an Angular project?

I recently added Bootstrap to my Angular project using the npm install bootstrap command and referencing the necessary CSS file in the styles property of the angular.json file. However, when I run my application, I notice that Bootstrap is not being applie ...

I could really use some assistance with the concept of "AJAX" - can anyone help

After spending several months working with AJAX, I have come to understand the typical request lifecycle: Sending parameters to a background page (PHP/ASP/HTML/TXT/XML ... what other options are available?) Performing server-side processing Receiv ...

Preventing the insertion of a line break when using Shift + Enter in Vuejs

Whenever I use a textarea to enter text, I find that I have to press Shift + Enter every time to send the text. However, upon sending, it adds /n at the end. I prefer using the Enter key for newline instead of submitting the form. Example: hello => ...

The `express.static` function does not seem to be functioning properly when used within the `express-p

I am currently in the process of refactoring a specific static route within my express application. Initially, if I include the following code snippet inside index.ts, it functions perfectly fine: import * as express from 'express'; const app = ...

Resolving the "Error: Cannot update a React state on an unmounted component" issue

I encountered a console error while attempting to navigate to a new page within my web application. Here's the error message I received: Warning: A React state update was attempted on an unmounted component, which is essentially a no-op. However, t ...

Is there a way to extract variables from a MySQL database and integrate them into a JavaScript function?

Hello everyone, I am looking to add markers on a map. In order to do this, I need to extract longitude and latitude from a database table. 1- I have used JavaScript to display the map (Google Maps). var map; var initialize; initialize = function( ...

Using NodeJS with Jade to handle a dynamic number of blocks

As I dive into NodeJS development, a challenge has presented itself... In my project, there is a main template called layout.jade that sets up the top navigation bar using Bootstrap on every page. This specific application focuses on music, where each art ...

Having trouble retrieving documents from a nested collection in Firebase

I am attempting to retrieve all documents from Firebase that are based on a query. Here is my current firebase structure: https://i.stack.imgur.com/tXrX8.png Even though I have two documents inside the "ListaFavorite" collection, when I check using empty ...