Как я могу заставить Angular Universal предварительно отображать контент из внешнего API?

Я хочу использовать SSR для улучшения поисковой оптимизации моего углового одностраничного приложения. Я включил SSR с помощью Angular-Universal, который работает для обслуживания статического html, но мои компоненты в значительной степени полагаются на асинхронные вызовы API для создания контента на странице. См. пример ниже, где $obs инициализируется в функции ngOnInit, а затем используется с каналом async в html для извлечения данных. Проблема, с которой я сталкиваюсь, заключается в том, что статический html, обслуживаемый SSR, не включает ничего, что использует канал async, эти вызовы выполняются на стороне клиента, а затем загружается содержимое. Это не то, что я хочу, потому что мне нужен контент из вызова API для создания метатегов. Можно ли заставить angular universal ждать завершения вызова API, отображать html с этими данными, а затем обслуживать статический 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();
  }
}

Я хочу, чтобы SSR отображал шаблон html с заголовком из вызова API, а затем обслуживал этот статический html.


person Jack Zavarella    schedule 20.08.2019    source источник
comment
Вам, вероятно, потребуется добавить маршрут на стороне сервера, который выполнял асинхронный/ожидающий запрос для одного и того же контента, чтобы заставить запрос ждать, пока контент не будет получен, прежде чем отображать ответ. Однако это относится только к паукам. Universal обслуживает index.html только один раз, если вы находитесь в браузере.   -  person Brandon    schedule 21.08.2019


Ответы (1)


В итоге я исправил свою проблему, которая была вызвана двумя разными проблемами:

Первая проблема: не показано в моем примере компонента, но это мой фактический код, я модифицировал объект document в первой строке метода ngOnInit, который при запуске приводил к сбою рендеринга на стороне сервера до того, как он попадал на http-вызов.

Вторая проблема: после удаления использования document мне нужно было добавить маршрут API в мой файл server.ts, чтобы проксировать запросы на серверную часть как @Brandon предложил.

const request = require('request');

app.get('/api/**', (req, res) => {
  const url = `${backendUrl}${req.originalUrl}`;
  request(url).pipe(res);
});
person Jack Zavarella    schedule 24.08.2019