从API请求Angular添加路由不适用于SSR

时间:2019-08-29 12:16:57

标签: angular api express routes server-side-rendering

我开始从事需要使用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 { }

settings.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能够加载路线。

1 个答案:

答案 0 :(得分:0)

您需要更改代码以使用路由初始化rootmodule

RouterModule.forRoot([])

收件人:

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

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

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