angular - 从 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 加载路由。
解决方案
您需要更改代码以使用路由初始化根模块
RouterModule.forRoot([])
至:
RouterModule.forRoot(
[{"path":"","component":"AppComponent"}]
)
然后,当您拥有路线时,您可以执行以下操作:
this.api.getSettings().subscribe(
response => {
...
this.router.resetConfig(s.routes);
...
},
...
推荐阅读
- bitbucket-server - 如何通过 Mulejob 从 Bitbucket 读取文件内容?
- continuous-integration - 如何使用环境配置自动将 Power BI (PBIX) 从桌面发布到 Power BI Web
- java - 如何将我的第一个 Jframe 表上的数据复制或复制到第二个 Jframe 表?
- drools - Drools - 理解这个示例,其中 drl 文件存储在与 kmodule 文件的 Kbase 名称属性不同的位置
- orbeon - 从表单运行器中删除不可用的项目
- dask - 我可以使用“client.upload_file”方法从 Dask 工作人员读取配置文件 (*.ini) 吗?
- angular - 单击 mat-option 自动完成时保留输入值 - Angular Material
- javascript - 如何使这个 Javascript 不区分大小写
- google-apps-script - 从 http 源加载 TEX 扩展失败
- liferay - Liferay 7 - 我需要使模拟用户 URL 动态化