如何解决使用 Angular 通用 dev:ssr 设置页面元标记有效但 build:ssr 不起作用
我在使用 Express 服务器构建和提供 Angular Universal 应用程序以获得良好的 SEO 方面遇到了挑战。
当我使用带有命令 "dev:ssr": "ng run motif:serve-ssr"
的脚本提供它并在默认端口 4200
上的浏览器上访问它并使用 Chrome 的查看页面源选项查看源时,我可以看到正确的动态元标记和还有 HTML 源代码,效果很好。
但是当我使用以下命令构建和提供它时,元标记没有被更新
"build:ssr": "ng build --prod && ng run motif:server:production"
npm run build:ssr && npm run serve:ssr
它构建和呈现时没有错误,但是当我在 Chrome 上查看页面源代码时,我只看到为 index.html
文件设置的元标记,但我希望它设置诸如页面标题、描述之类的标记每个文章数据的 、图像等。
我正在路由器数据解析器服务中设置元标记,它工作正常,因为我可以在运行 dev:ssr 脚本时看到它的工作。
CLI 版本是 9.1.12(v10 和 11v 有 ssr 和 window 对象的问题)。我是否遗漏了什么或做错了什么?
如果您对此问题有任何建议和解决方案,我将不胜感激。
更新:
数据解析器的简化版本如下:
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;
})
);
}
}
解决方法
我与您分享这项服务 不需要翻译的可以省略翻译服务
并尝试调用组件视图的构造函数或ngOnInit中的方法
import { Injectable } from '@angular/core';
import { Title,Meta } from '@angular/platform-browser';
import { TranslateService } from '@ngx-translate/core';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class SEOService {
constructor(private title: Title,private meta: Meta,private translate: TranslateService) {}
async getTranslation(word: string) {
if (word) {
return await this.translate
.get(word)
.toPromise()
.then(resp => {
return resp;
});
} else {
return '';
}
}
async updateTitle(title: string) {
const translation = await this.getTranslation(title);
this.title.setTitle(translation);
}
async updateDescription(desc: string) {
const translation = await this.getTranslation(desc);
this.meta.updateTag({ name: 'description',content: translation });
}
async updateKeywords(keywords: string) {
const translation = await this.getTranslation(keywords);
this.meta.updateTag({ name: 'keywords',content: translation });
}
async updateOgUrl(url: string) {
const translation = await this.getTranslation(url);
this.meta.updateTag({
name: 'og:url',property: 'og:url',content: translation
});
}
async updateOgTitle(ogTitle: string) {
const translation = await this.getTranslation(ogTitle);
this.meta.updateTag({
name: 'og:title',property: 'og:title',content: translation
});
}
async updateOgDescription(ogDesc: string) {
const translation = await this.getTranslation(ogDesc);
this.meta.updateTag({
name: 'og:description',property: 'og:description',content: translation
});
}
async updateOgImage(ogImg: string) {
const translation = await this.getTranslation(ogImg);
this.meta.updateTag({
name: 'og:image',property: 'og:image',content: translation
});
}
async disableFollow() {
this.meta.addTag({
name: 'robots',property: 'robots',content: 'noindex,nofollow'
});
}
async enableFollow() {
this.meta.removeTag('robots');
}
}
全局 ngOnInit 示例
import { Component,OnInit } from '@angular/core';
import {
Router,NavigationEnd,ActivatedRoute,RouterEvent
} from '@angular/router';
export class AppComponent implements OnInit {
constructor(
private router: Router,private route: ActivatedRoute,private seoService: SEOService,) {
}
ngOnInit() {
this.router.events
.pipe(
filter(event => event instanceof NavigationEnd),map(() => this.route),map(route => {
while (route.firstChild) {
route = route.firstChild;
}
return route;
}),filter(route => route.outlet === 'primary'),mergeMap(route => route.data)
)
.subscribe(event => {
this.seoService.updateTitle(event['title']);
this.seoService.updateDescription(event['description']);
this.seoService.updateKeywords(event['keywords']);
this.seoService.updateOgUrl(event['url']);
this.seoService.updateOgTitle(event['ogTitle']);
this.seoService.updateOgDescription(event['ogDesc']);
this.seoService.updateOgImage(event['ogImage']);
});
}
}
希望能帮到你 ;)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。