typescript Angular SSR transferState.get(key,null)返回null,但如果登录,我可以看到对象(都在浏览器中)

hs1rzwqc  于 2022-11-18  发布在  TypeScript
关注(0)|答案(1)|浏览(95)

在我正在开发的angular应用程序上,如果浏览器模拟一个中端移动的,会有一个明显的闪烁。当应用程序从服务器切换到浏览器时,angular似乎没有做Dom再水化,它完全取代了DOM。
然而,如果页面没有变化或者没有引入新的数据,这种影响应该是明显的。因此,为了减少这种影响,我试图确保服务器上的api调用不会重复。
代码库相当大,所以我不确定我是否会在这里放置任何相关的内容,但如果有任何遗漏,请在注解中询问。
我的App Server Module是:

import { NgModule } from '@angular/core';
import { ServerModule, ServerTransferStateModule } from '@angular/platform-server';
import { BrowserModule } from '@angular/platform-browser';
import { AppModule } from './app.module';
import { AppComponent } from './app.component';

@NgModule({
    imports: [
        AppModule,
        BrowserModule.withServerTransition({ appId: 'api-example' }),
        ServerModule,
        ServerTransferStateModule,
    ],
    bootstrap: [AppComponent],
})
export class AppServerModule {}

我的应用模块:

@NgModule({
    imports: [
        ConfigModule,
        TransferHttpCacheModule,
        AppRoutingModule,
        HttpClientModule,
        BrowserAnimationsModule,
        I18nModule,
        NgbModule,
        SwiperModule,
        ToastNoAnimationModule,
        NotificationModule,
        ToastrModule.forRoot({
            enableHtml: true,
            closeButton: true,
            positionClass: 'toast-top-right',
            toastClass: 'ngx-toastr',
            preventDuplicates: true,
        }),
        GoogleAnalyticsGTagModule,
        ProfileEditModalModule,
        NgcCookieConsentModule.forRoot(cookieConfig),
        FaqPageModule,
        CriticalApplicationErrorModule,
    ],
    declarations: [AppComponent],
    providers: [
        ...
        {
            provide: LocationStrategy,
            useClass: PathLocationStrategy,
        },
        {
            provide: HTTP_INTERCEPTORS,
            useClass: HttpInterceptorService,
            multi: true,
        },
    ],
    bootstrap: [AppComponent],
})
export class AppModule {}

这里值得注意的是,我没有使用单独的App Browser Module,也没有导入BrowserModule.withServerTransition({ appId: 'api-example'})BrowserTransferStateModule,因为当我这样做时,例如按照上一个链接中列出的指南操作时,它仍然会执行api调用,并且当页面在浏览器上重新加载时,它会丢失其样式此外,我可以在服务器和浏览器之间转换时打印存储在浏览器中的传输状态。
我还延迟了main.ts中的引导

document.addEventListener('DOMContentLoaded', () => {
    platformBrowserDynamic()
        .bootstrapModule(AppModule)
        .catch((err) => console.log(err));
});

然后使用HTTP Interceptor

public intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    if (request.method !== 'GET') {
        return next.handle(request);
    }

    const key: StateKey<string> = makeStateKey<string>(request.url);

    if (isPlatformServer(this.platformId)) {
        return next.handle(request).pipe(
            tap((event) => {
                this.transferState.set(key, (event as HttpResponse<any>).body);
                console.log(this.transferState.get(key, null) // Prints transferred stated item
            })
        );
    } else {
        const storedResponse = this.transferState.get<any>(key, null);
        console.log(storedResponse) // Prints null
        console.log(this.transferState) // Prints complete State
        console.log(this.transferState.get(key, null)) // Prints null
        if (storedResponse) {
            const response = new HttpResponse({ body: storedResponse, status: 200 });
            this.transferState.remove(key);
            return of(response);
        } else {
            return next.handle(request);
        }
    }
}

所以这就是我开始感到困惑的地方,完整地记录transferState可以工作,但如果我尝试使用transferState.get()就不行了,这是为什么呢?下面是浏览器中与this.transferState相关的console.log

Page Component中也是如此。
同样,如果我尝试使用JSON.parse(this.transferState.toJson()),它将只打印第一个存储的对象,因为它是i18n数据,所以有额外的缓存。如果缓存被禁用,i18n数据也不会从服务器传输到浏览器,否则它会从缓存中提取。
在页面组件上,正在使用API服务提取数据:

preparePageData(): void {
    this.server.getPageData().subscribe((res: any) => {
        this.pageData = res['data-details'];
    }
}

并且如果http get

getPageDate() {
    return this.http.get('http://example.com/getPageData')
}

导致此问题的原因是什么?
是否有任何其他信息对解决此问题有用?
如果我将BrowserModule.withServerTransition({ appId: 'api-example'})添加到我的应用模块或单独的App Browser Module中,我所有的样式都会被删除,这正常吗?
如果它可能是一个外部渲染器导致的问题,请告诉我什么寻找。
以下是我找到的一些可能相关的链接:
Angular Universal SSR TransferState only first page data available因为我使用SSR,而他使用静态页面,所以这不适用。
Angular Universal TransferState not loading on Client他的解决方案已经在我的代码库中实现了。
Angular - TransferState - page is loading twice (flickering)类似的问题,但没有解决方案可用。我也知道补液不是一件事,在角,(希望将在未来)。
Transfer State with Angular Tutorial on Ganatan.com已尝试使用此实现,但未解决此问题。它仍从服务器获取数据,并从客户端应用程序中删除了一些样式,但未从服务器应用程序中删除。
我做了更多的研究和阅读的文件,但这似乎是最相关的信息,我发现。

avwztpqn

avwztpqn1#

可能是服务器传输状态模块缺少您的应用程序.服务器.模块.ts
您的app.server.module.ts文件必须如下所示;

import { NgModule } from '@angular/core';
import { ServerModule, ServerTransferStateModule } from '@angular/platform-server';

import { AppComponent } from './app.component';
import { AppModule } from './app.module';

@NgModule({
  imports: [
    AppModule,
    ServerTransferStateModule,
    ServerModule,
  ],
  bootstrap: [AppComponent],
})
export class AppServerModule { }

相关问题