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.
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.
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.
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.
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);
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With