首页 > 解决方案 > 从 API 请求 Angular 添加路由不适用于 SSR

问题描述

我开始研究需要使用 API 请求从 CMS 加载特定路由的项目。

当使用“ng serve -o”在包含的代码下方运行时,所有路由都运行良好,但是一旦我在使用“npm build:ssr”进行构建后运行“npm serve:ssr”,路由就会停止工作。

此外,当 SRR 运行时,API 请求会执行 3 次,而不是没有 SSR 的情况下执行一次。

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule, APP_INITIALIZER } from '@angular/core';
import { RouterModule } from '@angular/router';
import { AppComponent } from './app.component';
import { SettingsService } from './services/settings.service';
import { ApiService } from './services/api.service';
import { HttpClientModule } from '@angular/common/http';
import { CommingSoonComponent } from './pages/comming-soon/comming-soon.component';

export function initSettings(settings: SettingsService) {
  return () => settings.loadSettings();
 }

@NgModule({
  declarations: [
    AppComponent,
    CommingSoonComponent
  ],
  imports: [
    BrowserModule.withServerTransition({ appId: 'serverApp' }),
    HttpClientModule,
    RouterModule.forRoot(
        []
      )
  ],
  entryComponents: [
    CommingSoonComponent
  ],
  providers: [
    SettingsService,
    ApiService,
    {
      'provide': APP_INITIALIZER,
      'useFactory': initSettings,
      'deps': [SettingsService],
      'multi': true,
    }
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

设置.service.ts

API 请求返回一个 JSON 对象:

{"routes":[{"path":"coming-soon","component":"CommingSoonComponent"}]}
import { Injectable, Injector } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Router, Routes } from '@angular/router';
import { routingComponents } from '../decorators/route.decorator';
import { ApiService } from './api.service';
import { Settings } from '../classes/Settings';

@Injectable({
  providedIn: 'root'
})
export class SettingsService {

  currentSettings: any;

  constructor( 
    private injector: Injector,
    private api: ApiService
    ) { }

    loadSettings(): Promise<any> {
      return new Promise((resolve, reject) => {
       setTimeout(() => {
          const router = this.injector.get(Router);
            this.api.getSettings().subscribe(
              response => {
                var obj = {};
                try {
                  obj = JSON.parse(response.d);
                } catch (error) {
                  return reject(false);
                }

                let s = new Settings
                Object.assign(s, obj)

                console.log(s);

                s.routes.forEach(elem => {
                  let component = routingComponents.get(elem.component);
                  if (component) {
                    console.log(component);
                    router.config.push({ path: elem.path, component: component 
                   })
                  }
                });

                return resolve(true);
            },
            err => {
              console.log(err);
              reject(false);
            }
          )
         });
      });
    }
}

控制台错误

ERROR Error: Uncaught (in promise): Error: Cannot match any routes. URL Segment: 'coming-soon'
Error: Cannot match any routes. URL Segment: 'coming-soon'

我希望有足够的信息可以使用 SSR 加载路由。

标签: angularapiexpressroutesserver-side-rendering

解决方案


您需要更改代码以使用路由初始化根模块

RouterModule.forRoot([])

至:

  RouterModule.forRoot(
        [{"path":"","component":"AppComponent"}]
  )

然后,当您拥有路线时,您可以执行以下操作:

this.api.getSettings().subscribe(
              response => {
               ...
               this.router.resetConfig(s.routes);
               ...
            },
...

推荐阅读