3

I'm having a problem with Angular Universal, although all guides are different (the official one seems outdated aswell) I've managed to run node.js server with server side rendering.
There's still a huge problem which I can't solve, because I actually have no idea on what's going on

This is the app.module.ts

@NgModule({
    declarations: [
        AppComponent
    ],
    imports: [
        HttpClientModule,
        BrowserModule.withServerTransition({
            appId: 'ta-un-certificate'
        }),
        RouterModule.forRoot([{
            path: '', loadChildren: './page/page.module#PageModule'
        }], {
            enableTracing: false,
            useHash: false
        }),
        TranslateModule.forRoot({
            loader: {
                provide: TranslateLoader,
                useFactory: HttpLoaderFactory,
                deps: [HttpClient]
            }
        })
    ],
    providers: [
        SeoService,
        DataService, {
            provide: HTTP_INTERCEPTORS,
            useClass: HttpErrorInterceptor,
            multi: true
        }],
    bootstrap: [
        AppComponent
    ]
})

It simply loads another module, PageModule with its components and stuff

@NgModule({
    imports: [
        CommonModule,
        TranslateModule,
        RouterModule.forChild([{
            path: ':name/:id', component: PageComponent
        }, {
            path: '', pathMatch: 'full', component: RedirectComponent
        }])
    ],
    declarations: [
        RedirectComponent,
        PageComponent,
        BannerComponent,
        BodyComponent,
        FooterComponent
    ]
})
export class PageModule {
}

For the server part, I made another module, app.server.module.ts which is the one used by node.js

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

The problem is that if I try to call a route from node.js server, eg. http://localhost:4000/foo/bar, the node.js server console prints out a huge error, starting with this:

Error: Uncaught (in promise): ReferenceError: navigator is not defined
[...]

(it's really huge, if u need something please ask) And page doesn't get rendered, as from cURL I get only <app-root><router-outlet></router-outlet></app-root> inside html body.

I think I've checked so many guides that I've completely lost the right way to do it, but cloning Angular Universal Starter seems doing what I'm expecting from Universal

CapitanFindus
  • 1,498
  • 15
  • 26
  • 1
    Are you using navigator in your code? Or a library that uses it? This won't be defined server side – David Feb 22 '18 at 09:20

1 Answers1

3

Searching on compiled server.js script, the one executed by node, it seemed like there was an error inside Translator. So I focused searching for issues between html rendering and Translation pipe, but then I've just found a navigator.language.split inside a service (app wasn't built by me). Moved that control inside a isPlatformServer block solved my issue.

This was the breaking part of code

private _language = navigator.language.split('-')[0];

constructor(private _http: HttpClient) {
}

Which I edited as following

private _language;

constructor(@Inject(PLATFORM_ID) private platformId,
            private _http: HttpClient) {

    if (isPlatformServer(this.platformId)) {
        this._language = 'en';
    } else {
        this._language = navigator.language.split('-')[0];
    }
}

Fixed the issue

CapitanFindus
  • 1,498
  • 15
  • 26