javascript - Angular server-side-rendering med rutteresolution


Jag försöker använda server-sidig rendering i Angular (v4) för att möjliggöra bättre SEO.

Saker fungerar som förväntat tills jag lägger till resolve på min rutt. Att lägga till resolve gör att HTML title behåller sitt ursprungliga värde när man tittar på källkoden.

Min modul:

import {
  Injectable,
  ModuleWithProviders,
  NgModule
} from '@angular/core';
import {
  ActivatedRouteSnapshot,
  Resolve,
  Router,
  RouterModule,
  RouterStateSnapshot
} from '@angular/router';
import {
  Observable
} from 'rxjs/Rx';

import {
  ArticleComponent
} from './article.component';
import {
  Article,
  ArticlesService,
  UserService,
  SharedModule
} from '../shared';

@Injectable()
export class ArticleResolver implements Resolve < Article > {
  constructor(
    private articlesService: ArticlesService,
    private router: Router,
    private userService: UserService
  ) {}

  resolve(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): any {
    return this.articlesService.get(route.params['slug'])
      .catch((err) => this.router.navigateByUrl('/'));
  }
}

const articleRouting: ModuleWithProviders = RouterModule.forChild([{
  path: 'article/:slug',
  component: ArticleComponent,
  resolve: {
     article: ArticleResolver
  },
  data: {
    preload: true
  }
}]);

@NgModule({
  imports: [
    articleRouting,
    SharedModule
  ],
  declarations: [
    ArticleComponent
  ],

  providers: [
    ArticleResolver
  ]
}) export class ArticleModule {}

Min komponent:

import {
  Component,
  OnInit
} from '@angular/core';
import {
  ActivatedRoute,
  Router,
} from '@angular/router';
import {
  Title,
  Meta
} from '@angular/platform-browser';

import {
  AppComponent
} from '../app.component';

import {
  Article,
} from '../shared';

@Component({
  selector: 'article-page',
  templateUrl: './article.component.html'
})
export class ArticleComponent implements OnInit {
  article: Article;

  constructor(
    private route: ActivatedRoute,
    private meta: Meta,
    private title: Title
  ) {}

  ngOnInit() {
    this.route.data.subscribe(
      (data: {
        article: Article
      }) => {
        this.article = data.article;
      }
    );
    this.title.setTitle(this.article.title);
  }
}

Jag är ny på Angular SSR så all vägledning uppskattas mycket.

Svar #1

Istället för att prenumerera på ruttdata, hämta dina resultat från ögonblicksbilden på detta sätt:

this.route.snapshot.data['article']

Du kan också behöva registrera ArticlesService i dina providers för modulen.

Som en parentes, denna import:

import {
  Observable
} from 'rxjs/Rx';

är ett RxJS-antimönster. Använd istället följande import:

import {Observable} from 'rxjs/Observable';

Svar #2

Jag upptäckte att min primära tjänst refererade till en sekundär tjänst som försökte returnera en autentiseringstoken från window.localStorage.

Försök att få åtkomst till klientlagring fick Angular SSR att utebli genereringen av källkod för min komponent.

Tack @Adam_P för att du hjälpte mig att gå igenom det!

Relaterade artiklar