Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I force Angular Universal to pre-render content from an external api?

I want to use SSR to improve search engine optimization on my angular single page application. I have enabled SSR by using Angular-Universal which is working to serve the static html but my components heavily rely on asynchronous api calls to build the content on the page. See the example below where the $obs is initialized in the ngOnInit function and then used with the async pipe in the html to pull out data. The problem I am having is the static html served by the SSR does not include anything that uses an async pipe, these calls are made on the client side and then the content is loaded. This is not what I want because I need the content from the api call to generate meta tags. Is it possible to force angular universal to wait for the api call to finish, render the html with this data and then serve the static html?

@Component({
  selector: 'app-example-component',
  template: `
    <div *ngIf="(obs$ | async) as model">
      {{model.title}}
    </div>
  `
})
export class ExampleComponent implements OnInit {

  obs$: Observable<SomeModel>;

  constructor(private exampleHttpService: ExampleHttpService) {}

  ngOnInit() {
    this.obs$ = this.exampleHttpService.doSomeApiCall();
  }
}

I want the SSR to render the template html with the title from the api call then serve that static html.

like image 960
Jack Zavarella Avatar asked Aug 20 '19 22:08

Jack Zavarella


People also ask

What is Prerender in Angular universal?

Angular Universal lets you prerender the pages of your application. Prerendering is the process where a dynamic page is processed at build time generating static HTML.

What is Angular universal state transfer API?

The TransferState API introduced in Angular v5 can help in this situation. It can transfer data from the server side of the app to the browser app. For this, the server app will add the data we want to transfer in the HTML page it generates.

Is server-side rendering possible in Angular?

Angular applications are client-side applications that execute on the browser - which means they are rendered on the client, not on the server. You can add server-side rendering to your app using Angular Universal.


1 Answers

I ended up fixing my issue which was being caused by two different problems:

First problem: Not shown in my example component but it my actual code, I was modifying the document object in the first line of the ngOnInit method which when ran would cause the server side rendering to fail before it got to the http call.

Second problem: After removing usage of document, I needed to add an api route to my server.ts file to proxy the requests to the backend as @Brandon suggested.

const request = require('request');

app.get('/api/**', (req, res) => {
  const url = `${backendUrl}${req.originalUrl}`;
  request(url).pipe(res);
});
like image 51
Jack Zavarella Avatar answered Oct 23 '22 06:10

Jack Zavarella