[英]Setting page meta tags with Angular universal dev:ssr works but build:ssr is not working
我在使用快速服務器構建和提供 Angular 通用應用程序以實現良好的 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']);
});
}
}
希望這可以幫到你;)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.