簡體   English   中英

使用 Angular 通用 dev:ssr 設置頁面元標記有效,但 build:ssr 無效

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM