2

I have an Angular 7 application with Angular Universal implemented. It's a pretty big application with several lazy loaded modules. I use the TransferState module, and everything goes well, eeeeexcept that in some pages, the script injected by the TransferState module is "double". There are at least two instances, like:

<script id="myapp-state">{ objectA }</script>
<script id="myapp-state">{ objectB }</script>

And what's worse, the content inside both is different. Therefore, when the client app loads, sometimes it tries to retrieve data that is stored in objectB but cannot find it in objectA, which is the one checked because... it's the first one? (That's internal logic of the TransferState module, I assume).

I don't have too many hopes on an answer, since I can't really provide too much documentation, but maybe someone has experienced a similar issue.

What could be the reason? What part of the TransferState module is in charge of injecting this script and why doesn't it throw an error when there's already one?

Update:

Here's the main.browser.ts file:

if (environment.production) {
    enableProdMode();
}

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

and here's the main.server.ts file:

if (environment.production) {
    enableProdMode();
}

export { ServerAppModule } from './app/server.app.module';

My server.app.module.ts:

@NgModule({
    bootstrap: [
        AppComponent
    ],
    imports: [
        AppModule,
        ServerModule,
        BrowserModule.withServerTransition({
            appId: APPLICATION_NAME
        }),
        NoopAnimationsModule,
        ModuleMapLoaderModule,
        ServerTransferStateModule
    ]
})
export class ServerAppModule {
}

and my browser.app.module:

@NgModule({
    bootstrap: [
        AppComponent
    ],
    imports: [
        BrowserModule.withServerTransition({
            appId: APPLICATION_NAME
        }),
        BrowserAnimationsModule,
        BrowserTransferStateModule,
        AppModule
    ]
})
export class BrowserAppModule {
}

And the engine part of my server.ts:

app.engine('html', (filePath, options, callback) => {
        const engine = ngExpressEngine({
            bootstrap: ServerAppModuleNgFactory,
            providers: [
                provideModuleMap(LAZY_MODULE_MAP),
                { provide: REQUEST, useFactory: () => (options as any).req, deps: [] },
                { provide: RESPONSE, useFactory: () => (options as any).req.res, deps: [] },
                { provide: LOCALES, useFactory: () => allLocalizationStrings, deps: [] },
            ]
        });

        engine(filePath, options as any, callback);
    });

UPDATE: It seems to be related with my pre rendering. If I deactivate it, everything works correctly. If I activate it, it does not work correctly regardless of the route I'm rendering. This is how I'm pre rendering at the moment:

const html = await renderModuleFactory(ServerAppModuleNgFactory, {
                document: baseIndex,
                url: route,
                extraProviders: [
                    provideModuleMap(LAZY_MODULE_MAP),
                    { provide: IS_PRE_RENDER, useFactory: () => true, deps: [] },
                    { provide: ERROR_WRAPPER, useValue: (errorWrapper) }
                ]
            });
RTYX
  • 1,244
  • 1
  • 14
  • 32
  • Can you show your `server.ts` and `main.ts` files? – David Nov 04 '19 at 08:09
  • Sure. I added some of it already. The server.ts is a bit too long, but I can add more if you are interested in something in particular. – RTYX Nov 04 '19 at 14:40
  • Any update on this? I am having 2 TransferState script Tags and the first one is always empty which makes the whole transferState useless – Jeremias Nater Sep 28 '21 at 15:18

0 Answers0