skip to Main Content

I am attempting to use Server-Side Rendering in Angular (v4) to allow for better SEO.

Things work as expected until I add resolve on my route. Adding resolve causes HTML title to retain it’s initial value when viewing source.

My Module:

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 {}

My Component:

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);
  }
}

I am new to Angular SSR so any guidance is greatly appreciated.

2

Answers


  1. Chosen as BEST ANSWER

    I found that my primary service was referencing a secondary service that was attempting to return an authentication token from window.localStorage.

    Attempting to access the client storage caused Angular SSR to omit the generation of source code for my component.

    Thanks @Adam_P for helping me walk through it!


  2. Instead of subscribing to route data, retrieve your results from the snapshot like this:

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

    You also might need to register ArticlesService in your providers for the module.

    As a side note, this import:

    import {
      Observable
    } from 'rxjs/Rx';
    

    is an RxJS antipattern. Please use the following import instead:

    import {Observable} from 'rxjs/Observable';
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search