I am having a challenge with building and serving an Angular Universal application with the express server for good SEO.
When I serve it with the script with command "dev:ssr": "ng run motif:serve-ssr" and access it on the browser on the default port 4200 and view the source using the Chrome's view page source option, I can see the correct dynamic meta tags and also the HTML source, which works perfect.
But when I build and serve it with the below commands, the meta tags are not being updated
"build:ssr": "ng build --prod && ng run motif:server:production"
npm run build:ssr && npm run serve:ssr
It builds and renders with no errors, but when I view the page source on Chrome I see only the meta tags set for the index.html file but I am expecting it to set the tags like the page title, description, image etc for each article data.
I am setting the meta tags in a router data resolver service, and it works fine because I can see its works when running the dev:ssr script.
The CLI version is 9.1.12 (v10 & 11v having issues with ssr and the window object). Am I missing something or doing something wrong?
I'd appreciate any suggestions and solutions to this issue.
Update:
A simplified version of the data resolver is below:
import { Injectable } from '@angular/core';
import { AngularFirestore } from '@angular/fire/firestore';
import { DomSanitizer, TransferState } from '@angular/platform-browser';
import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router';
import { SeoSocialShareData, SeoSocialShareService } from 'ngx-seo';
import { Observable, of, Subscription } from 'rxjs';
import { map } from 'rxjs/operators';
@Injectable({ providedIn: 'root' })
export class ArticleDataResolver implements Resolve<any> {
constructor(
private seoSocialShareService: SeoSocialShareService,
private angularFirestore: AngularFirestore,
) { }
resolve(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<any> | Promise<any> | any {
const stateKey = state.url;
const ref = this.angularFirestore.collection("movementArticles");
return ref
.doc(route.params.id)
.get()
.pipe(
map((dataSnap) => {
const seoData: SeoSocialShareData = {
title: '...',
description: '...',
image: '...',
author: '...',
keywords: `...`,
url: `...`,
published: '...',
};
this.seoSocialShareService.setData(seoData);
return dataSnap;
})
);
}
}