Angular Universal 构建因 API 请求而卡在预渲染页面上

标签 angular typescript angular-cli angular-universal

我正在开发一个基于 angular universal starter 的小型网络应用程序和 pokeapi 。由于我想要显示的许多数据实际上并没有改变,因此我想使用预渲染页面来减少对 API 的请求数量并提高性能。对于我的示例,我在应用程序的主页上放置了一个神奇宝贝列表,我从 API 中检索该列表。

export class HomeComponent implements OnInit {

    pokemon$: ReplaySubject<ResourceList> = new ReplaySubject<ResourceList>();

    constructor(private pokedexService: PokedexService, private state: TransferState) { }

    ngOnInit() {
        if (this.state.hasKey(STATE_KEY_POKEMON)) {
            this.pokemon$.next(this.state.get(STATE_KEY_POKEMON, {} as ResourceList));
        }
        else {
            this.pokedexService.getResourceByCategory(ResourceCategory.POKEMON)
                .subscribe((resourceList: ResourceList) => {
                    this.pokemon$.next(resourceList);
                    this.state.set(STATE_KEY_POKEMON, resourceList.results);
                });
        }
    }
}

当我让客户端渲染页面时,这工作得很好。但是,当我尝试预渲染应用程序时,构建过程会挂起。由于我正在运行 API 的本地实例,因此我可以看到发出了请求并且返回了 200 状态。构建日志如下所示:

npm run build:prerender

> <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="ddb3baf0a8b3b4abb8afaebcb1f0b9b8b0b29dedf3edf3ed" rel="noreferrer noopener nofollow">[email protected]</a> build:prerender C:\Users\thijs\Development\pokedex universal\angular-universal-pokedex
> npm run build:client-and-server-bundles && npm run compile:server && npm run generate:prerender


> <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="a4cac389d1cacdd2c1d6d7c5c889c0c1c9cbe4948a948a94" rel="noreferrer noopener nofollow">[email protected]</a> build:client-and-server-bundles C:\Users\thijs\Development\pokedex universal\angular-universal-pokedex
> ng build --prod && ng run ng-universal-demo:server:production


Date: 2018-09-22T16:47:41.687Z
Hash: c49708f1ccb7e73e327a
Time: 8181ms
chunk {0} runtime.6afe30102d8fe7337431.js (runtime) 1.05 kB [entry] [rendered]
chunk {1} styles.34c57ab7888ec1573f9c.css (styles) 0 bytes [initial] [rendered]
chunk {2} polyfills.c174e4dc122f769bd68b.js (polyfills) 64.3 kB [initial] [rendered]
chunk {3} main.19481e4ceb7a5808fe78.js (main) 312 kB [initial] [rendered]

Date: 2018-09-22T16:47:50.816Z
Hash: ee7e30e1f9c277bb5cbf
Time: 5739ms
chunk {main} main.js (main) 38.2 kB [entry] [rendered]

> <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="1e7079336b7077687b6c6d7f72337a7b73715e2e302e302e" rel="noreferrer noopener nofollow">[email protected]</a> compile:server C:\Users\thijs\Development\pokedex universal\angular-universal-pokedex
> tsc -p server.tsconfig.json


> <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="6c020b411902051a091e1f0d0041080901032c5c425c425c" rel="noreferrer noopener nofollow">[email protected]</a> generate:prerender C:\Users\thijs\Development\pokedex universal\angular-universal-pokedex
> cd dist && node prerender

完成预渲染构建的唯一方法是删除网络请求。我想肯定还有什么东西在后台运行。我尝试将 Observable 切换为 Promise,但这并没有改变任何东西。我错过了什么?

You can find my project on GitHub .

最佳答案

有点晚了,但是如果有人遇到困难,这可能会有所帮助:

Similarly to the above section on waiting for macrotasks to complete, the flip-side is that the platform will not wait for microtasks to complete before finishing the render. In Angular Universal, we have patched the Angular HTTP client to turn it into a macrotask, to ensure that any needed HTTP requests complete for a given render. However, this type of patch may not be appropriate for all microtasks, and so it is recommended you use your best judgment on how to proceed. You can look at the code reference for how Universal wraps a task to turn it into a macrotask, or you can simply opt to change the server behavior of the given tasks.

基本上,如果您的 http 请求花费太长时间,预渲染就会挂起并且无法完成。 websocket 连接也是如此(firebase 在 angular-firebase 中使用 WS)。 另外,当我遇到这个问题时,终端中没有错误输出,这使得调试非常困难。 我建议如下:

  • WS 连接仅在 CSR 上,将它们也包装在 if 语句中
  • 对于 SSR 或静态预渲染,请使用 REST API 端点并确保不会收到任何超时错误。

关于Angular Universal 构建因 API 请求而卡在预渲染页面上,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52458865/

相关文章:

javascript - 使用模型 [Angular] 的嵌套对象填充选择下拉列表

node.js - 如何在 MEAN 堆栈应用程序中从后端到前端进行通信?

angular - ionic 电容器本地通知

angular - 如何将 core-js 映射导入到 angular-cli webpack 生成的应用程序中

angular - 如何将 gulp 任务添加到 Angular cli 构建中

angular - 如何在 Angular-CLI 6+ 中省略源映射

angular - 条件脚本包含取决于环境

拦截器错误中的 Angular 2 重定向

typescript - 如何向现有类型添加静态方法?

typescript - 没有泛型的类型推断?