Angular NgRx/Store 的通用 Http 错误
Angular Universal Http Errors with NgRx/Store
我正在尝试使用 Angular Universal 完成服务器端渲染并预渲染它:
Server.ts
import 'zone.js/dist/zone-node';
import 'reflect-metadata';
import {renderModuleFactory} from '@angular/platform-server';
import * as express from 'express';
import { readFileSync } from 'fs';
import { enableProdMode } from '@angular/core';
import { ngExpressEngine } from '@nguniversal/express-engine';
import { provideModuleMap } from '@nguniversal/module-map-ngfactory-loader';
const {AppServerModuleNgFactory, LAZY_MODULE_MAP} = require('./dist-server/main');
enableProdMode();
const app = express();
const distFolder = __dirname + '/dist';
app.engine('html', ngExpressEngine({
bootstrap: AppServerModuleNgFactory,
providers: [provideModuleMap(LAZY_MODULE_MAP)]
}));
app.set('view engine', 'html');
app.set('views', distFolder);
app.get('*.*', express.static(distFolder, {
maxAge: '1y'
}));
app.get('*', (req, res) => {
res.render('index', {req});
});
app.listen(9000, () => {
console.log(`Angular Universal Node Express server listening on http://localhost:9000`);
});
http 的主机名和令牌取自 ngRx/store,如下所示:
constructor(
private http: HttpClient,
private authService: AuthService,
private store: Store<AppState>
) {
this.store.select(getHostname)
.subscribe((res) => this.URL = res);
}
getCoursesModules(): Observable<UniModule[]> {
return this.store.select(getAuthToken)
.pipe(
take(1),
flatMap((token) => this.http.get(`${this.URL}/ROS/applications/1000001/modules?token=${token}`)),
map((res: any) => res.data.map((module) => this.mapModule(module)))
);
}
但是当 运行 prerender.ts 和 ts.node
我看到发送的请求没有主机名和令牌:
console.log(请求)在 error.interceptor 中的结果:
http:///UnibookHsisRest/share?token=null&typeId=0
http:///ROS/applications/1000001/modules?token=null
路由-table:
const appRoutes: Routes = [
{ path: 'Authentication', component: AuthComponent},
{path: '', redirectTo: 'home', pathMatch: 'full'},
{ path: 'home', component: HomeComponent, children: [
{path: 'students', component: MycoursesStudentComponent},
],
canActivate: [AuthGuard], resolve: {sign: SignInResolver}}
];
能否请一些人提供有关解决方案的想法?提前致谢
还根据问题添加以下代码:https://github.com/ngrx/platform/issues/101
export function stateSetter(reducer: ActionReducer<any>): ActionReducer<any> {
return function(state: any, action: any) {
if (action.type === 'SET_ROOT_STATE') {
return action.payload;
}
return reducer(state, action);
};
}
const _metaReducers: MetaReducer<fromRoot.State, any>[] = [stateSetter];
if ( !environment.production ) {
_metaReducers.push( debugMetaReducer );
}
export const metaReducers = _metaReducers;
export const NGRX_STATE = makeStateKey('NGRX_STATE');
const modules = [
StoreModule.forRoot(fromRoot.reducers, { metaReducers }),
HttpClientModule,
RouterModule,
routing,
BrowserModule.withServerTransition({
appId: 'store-app'
}),
BrowserTransferStateModule,
];
const services = [
{
provide: RouterStateSerializer,
useClass: MyRouterStateSerializer,
}
];
const containers = [
AppComponent,
HomeComponent,
];
@NgModule({
bootstrap: [AppComponent],
declarations: [
...containers
],
imports: [
...modules,
BrowserModule.withServerTransition({ appId: 'store-app' }),
StoreRouterConnectingModule,
],
providers: [
...services,
],
})
export class AppModule {
public constructor(
private readonly transferState: TransferState,
private readonly store: Store<fromRoot.State>,
) {
const isBrowser = this.transferState.hasKey<any>(NGRX_STATE);
if (isBrowser) {
this.onBrowser();
} else {
this.onServer();
}
}
onServer() {
this.transferState.onSerialize(NGRX_STATE, () => {
let state;
this.store.subscribe( ( saveState: any ) => {
// console.log('Set for browser', JSON.stringify(saveState));
state = saveState;
}).unsubscribe();
return state;
});
}
onBrowser() {
const state = this.transferState.get<any>(NGRX_STATE, null);
this.transferState.remove(NGRX_STATE);
this.store.dispatch( { type: 'SET_ROOT_STATE', payload: state } );
// console.log('Got state from server', JSON.stringify(state));
}
}
按照此 post 解决问题。
https://github.com/ngrx/platform/issues/101
我正在尝试使用 Angular Universal 完成服务器端渲染并预渲染它:
Server.ts
import 'zone.js/dist/zone-node';
import 'reflect-metadata';
import {renderModuleFactory} from '@angular/platform-server';
import * as express from 'express';
import { readFileSync } from 'fs';
import { enableProdMode } from '@angular/core';
import { ngExpressEngine } from '@nguniversal/express-engine';
import { provideModuleMap } from '@nguniversal/module-map-ngfactory-loader';
const {AppServerModuleNgFactory, LAZY_MODULE_MAP} = require('./dist-server/main');
enableProdMode();
const app = express();
const distFolder = __dirname + '/dist';
app.engine('html', ngExpressEngine({
bootstrap: AppServerModuleNgFactory,
providers: [provideModuleMap(LAZY_MODULE_MAP)]
}));
app.set('view engine', 'html');
app.set('views', distFolder);
app.get('*.*', express.static(distFolder, {
maxAge: '1y'
}));
app.get('*', (req, res) => {
res.render('index', {req});
});
app.listen(9000, () => {
console.log(`Angular Universal Node Express server listening on http://localhost:9000`);
});
http 的主机名和令牌取自 ngRx/store,如下所示:
constructor(
private http: HttpClient,
private authService: AuthService,
private store: Store<AppState>
) {
this.store.select(getHostname)
.subscribe((res) => this.URL = res);
}
getCoursesModules(): Observable<UniModule[]> {
return this.store.select(getAuthToken)
.pipe(
take(1),
flatMap((token) => this.http.get(`${this.URL}/ROS/applications/1000001/modules?token=${token}`)),
map((res: any) => res.data.map((module) => this.mapModule(module)))
);
}
但是当 运行 prerender.ts 和 ts.node 我看到发送的请求没有主机名和令牌:
console.log(请求)在 error.interceptor 中的结果:
http:///UnibookHsisRest/share?token=null&typeId=0
http:///ROS/applications/1000001/modules?token=null
路由-table:
const appRoutes: Routes = [
{ path: 'Authentication', component: AuthComponent},
{path: '', redirectTo: 'home', pathMatch: 'full'},
{ path: 'home', component: HomeComponent, children: [
{path: 'students', component: MycoursesStudentComponent},
],
canActivate: [AuthGuard], resolve: {sign: SignInResolver}}
];
能否请一些人提供有关解决方案的想法?提前致谢
还根据问题添加以下代码:https://github.com/ngrx/platform/issues/101
export function stateSetter(reducer: ActionReducer<any>): ActionReducer<any> {
return function(state: any, action: any) {
if (action.type === 'SET_ROOT_STATE') {
return action.payload;
}
return reducer(state, action);
};
}
const _metaReducers: MetaReducer<fromRoot.State, any>[] = [stateSetter];
if ( !environment.production ) {
_metaReducers.push( debugMetaReducer );
}
export const metaReducers = _metaReducers;
export const NGRX_STATE = makeStateKey('NGRX_STATE');
const modules = [
StoreModule.forRoot(fromRoot.reducers, { metaReducers }),
HttpClientModule,
RouterModule,
routing,
BrowserModule.withServerTransition({
appId: 'store-app'
}),
BrowserTransferStateModule,
];
const services = [
{
provide: RouterStateSerializer,
useClass: MyRouterStateSerializer,
}
];
const containers = [
AppComponent,
HomeComponent,
];
@NgModule({
bootstrap: [AppComponent],
declarations: [
...containers
],
imports: [
...modules,
BrowserModule.withServerTransition({ appId: 'store-app' }),
StoreRouterConnectingModule,
],
providers: [
...services,
],
})
export class AppModule {
public constructor(
private readonly transferState: TransferState,
private readonly store: Store<fromRoot.State>,
) {
const isBrowser = this.transferState.hasKey<any>(NGRX_STATE);
if (isBrowser) {
this.onBrowser();
} else {
this.onServer();
}
}
onServer() {
this.transferState.onSerialize(NGRX_STATE, () => {
let state;
this.store.subscribe( ( saveState: any ) => {
// console.log('Set for browser', JSON.stringify(saveState));
state = saveState;
}).unsubscribe();
return state;
});
}
onBrowser() {
const state = this.transferState.get<any>(NGRX_STATE, null);
this.transferState.remove(NGRX_STATE);
this.store.dispatch( { type: 'SET_ROOT_STATE', payload: state } );
// console.log('Got state from server', JSON.stringify(state));
}
}
按照此 post 解决问题。 https://github.com/ngrx/platform/issues/101