Transloco: Support Universal

Created on 21 Aug 2019  路  8Comments  路  Source: ngneat/transloco

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[ ] Bug report  
[ ] Performance issue
[x] Feature request
[ ] Documentation issue or request
[ ] Support request
[ ] Other... Please describe:

Current behavior

Universal build errors out - I got the same error with HTTP loader and Webpack loader. I couldn't find docs around which to choose or why.

Expected behavior

Universal build succeeds

Minimal reproduction of the problem with instructions

Run ng new and implement ng-universal using the schematic:

ng add @nguniversal/express-engine --clientProject <PROJECT-NAME>

Initially it complained about no fallback language. I remedied that, tried again and got this error:

ERROR Error: Unable to load translation and all the fallback languages
    at TranslocoService.handleFailure (/Users/jamieperkins/Web-projects/Cloud_servers/my-project/dist/webpack/server.js:232909:19)
    at CatchSubscriber.selector (/Users/jamieperkins/Web-projects/Cloud_servers/my-project/dist/webpack/server.js:232604:40)
    at CatchSubscriber.error (/Users/jamieperkins/Web-projects/Cloud_servers/my-project/dist/webpack/server.js:34170:31)
    at RetrySubscriber.Subscriber._error (/Users/jamieperkins/Web-projects/Cloud_servers/my-project/dist/webpack/server.js:28210:26)
    at RetrySubscriber.Subscriber.error (/Users/jamieperkins/Web-projects/Cloud_servers/my-project/dist/webpack/server.js:28190:18)
    at RetrySubscriber.error (/Users/jamieperkins/Web-projects/Cloud_servers/my-project/dist/webpack/server.js:36995:47)
    at MapSubscriber.Subscriber._error (/Users/jamieperkins/Web-projects/Cloud_servers/my-project/dist/webpack/server.js:28210:26)
    at MapSubscriber.Subscriber.error (/Users/jamieperkins/Web-projects/Cloud_servers/my-project/dist/webpack/server.js:28190:18)
    at FilterSubscriber.Subscriber._error (/Users/jamieperkins/Web-projects/Cloud_servers/my-project/dist/webpack/server.js:28210:26)
    at FilterSubscriber.Subscriber.error (/Users/jamieperkins/Web-projects/Cloud_servers/my-project/dist/webpack/server.js:28190:18)

What is the motivation / use case for changing the behavior?

For Universal to work

Environment


Angular CLI: 7.3.9
Angular: 7.2.15


Browser:
- [x ] Chrome (desktop) version 76
- [ ] Chrome (Android) version XX
- [ ] Chrome (iOS) version XX
- [ ] Firefox version XX
- [ ] Safari (desktop) version XX
- [ ] Safari (iOS) version XX
- [ ] IE version XX
- [ ] Edge version XX

For Tooling issues:

Node: 8.15.1
OS: darwin x64

Others:

enhancement help wanted

Most helpful comment

I found the issue. When working with SSR, you need to set the absolute URL. Add in your environment file a baseUrl property:

export const environment = {
  production: false,
  baseUrl: 'http://localhost:4000'
};

And in the HTTP loader use it like:

import { HttpClient } from '@angular/common/http';
import { Translation, TRANSLOCO_LOADER, TranslocoLoader } from '@ngneat/transloco';
import { Injectable } from '@angular/core';
import { environment } from '../environments/environment';

@Injectable({ providedIn: 'root' })
export class HttpLoader implements TranslocoLoader {
  constructor(private http: HttpClient) { }

  getTranslation(langPath: string) {
    return this.http.get<Translation>(`${environment.baseUrl}/assets/i18n/${langPath}.json`);
  }
}

export const translocoLoader = { provide: TRANSLOCO_LOADER, useClass: HttpLoader };

I tested it, and it works fine. Let me know if it worked for you so I will add it to the docs and the schematics.

All 8 comments

I see the issue. I changed the loader, so it returns a static of observable, and it worked. We need to investigate further what's the problem. I never used Angular's SSR.

I uploaded a demo repository.

I found the issue. When working with SSR, you need to set the absolute URL. Add in your environment file a baseUrl property:

export const environment = {
  production: false,
  baseUrl: 'http://localhost:4000'
};

And in the HTTP loader use it like:

import { HttpClient } from '@angular/common/http';
import { Translation, TRANSLOCO_LOADER, TranslocoLoader } from '@ngneat/transloco';
import { Injectable } from '@angular/core';
import { environment } from '../environments/environment';

@Injectable({ providedIn: 'root' })
export class HttpLoader implements TranslocoLoader {
  constructor(private http: HttpClient) { }

  getTranslation(langPath: string) {
    return this.http.get<Translation>(`${environment.baseUrl}/assets/i18n/${langPath}.json`);
  }
}

export const translocoLoader = { provide: TRANSLOCO_LOADER, useClass: HttpLoader };

I tested it, and it works fine. Let me know if it worked for you so I will add it to the docs and the schematics.

Thanks! It's working for me.

Great. @itayod will add it to the schematics.

@NetanelBasal Kind of a side question but could you explain in the docs why you should choose the Webpack or HTTP loader?

@inorganik Currently, I can't find any benefit of one over the other, but we like to give options.

what's the differerence? I am clueless

With Webpack, for example, you can load typescript files. But maybe we should remove this option from our schematics as it's confusing.

Was this page helpful?
0 / 5 - 0 ratings