question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

performance question: directive vs pipe

See original GitHub issue

I’m submitting a … (check one with “x”)

[ ] bug report => check the FAQ and search github for a similar issue or PR before submitting
[x] support request => check the FAQ and search github for a similar issue before submitting
[ ] feature request

Is there a performance advantage to using the translate directive vs the (impure) translate pipe?

Issue Analytics

  • State:open
  • Created 6 years ago
  • Comments:11

github_iconTop GitHub Comments

5reactions
albanxcommented, May 29, 2019

@piotr-szybicki The pipe

import { Pipe, PipeTransform } from '@angular/core';
import { TranslateService } from '@services/translate.service';

@Pipe({
  name: '_'
})
export class TranslatePipe implements PipeTransform {
  constructor(public trans: TranslateService) {}

  transform(value: string, ...args): string {
    if (args.length > 1) {
      args.shift();
    }
    return this.trans._(value, args);
  }
}

The service:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { LANGUAGES } from '@constants/languages';
import { Store } from '@ngrx/store';
import AppState from '@state/app.state';
import { environment } from 'environments/environment';

@Injectable({
  providedIn: 'root'
})
export class TranslateService {
  public lang: string;
  dictionary: any = {};
  _collector: any = {};
  deployUrl = environment.deployUrl;

  constructor(private http: HttpClient, private store: Store<AppState>) {
    this.store.select(state => state.settings).subscribe(settings => this.setLanguage(settings.language));
  }

  public _(val: string, args = []) {
    const translated = this.dictionary[val] ? this.dictionary[val] : val;
    this._collector[val] = translated;

    if (args.length > 0) {
      return this.sprintf(translated, args);
    }

    return translated;
  }

  public setLanguage(lang: string) {
    if (LANGUAGES[lang]) {
      this.loadLanguage(lang, `${this.deployUrl}/${LANGUAGES[lang].path}`);
    }
  }

  private sprintf(val: string, args: Array<string>) {
    return args.reduce((p, c) => p.replace(/%s/, c), val);
  }

  private loadLanguage(lang: string, url: string) {
    console.log(JSON.stringify(this._collector));

    return this.http.get(url).subscribe(dictionary => {
      this.dictionary = dictionary;
      this.lang = lang;
    });
  }
}

A component usage (that also switch the language):

import { Component, OnInit } from '@angular/core';
import { environment } from 'environments/environment';
import { Store } from '@ngrx/store';
import AppState from '@state/app.state';
import { buildSetLanguage } from '@state/actions/settings.actions';
import { TranslateService } from '@services/translate.service';
@Component({
  selector: 'app-footer',
  templateUrl: './footer.component.html',
  styleUrls: ['./footer.component.scss']
})
export class FooterComponent implements OnInit {
  brand = environment.brand;
  version = environment.appVersion;
  constructor(private store: Store<AppState>, public trans: TranslateService) {}

  ngOnInit() {}

  setLanguage(lang) {
    this.store.dispatch(buildSetLanguage(lang));
  }
}

.html

<footer class="footer">
  <p class="footer__copyright">
    <a class="footer__link" href="https://{{ brand.url }}">© {{ brand.name }}</a> |
    <a class="footer__link" (click)="setLanguage('en')"> English </a> |
    <a class="footer__link" (click)="setLanguage('sq')"> Shqip </a>
  </p>
  <p class="termsofuse">
    <a class="footer__link" routerLink="/legal/about">{{ 'About' | _: trans.lang }} </a> |
    <a class="footer__link" routerLink="/legal/terms">{{ 'Terms of Use' | _: trans.lang }}</a> |
    <a class="footer__link" routerLink="/legal/privacy">{{ 'Privacy and GDPR' | _: trans.lang }}</a>
  </p>
  <p class="termsofuse">Version {{ version }}</p>
</footer>

Hope this helps.

The basic idea is that the language get changed/checked only when it changes, not on every change detection cycles.

4reactions
albanxcommented, Jan 27, 2019

Using impure pipes can lead to several performance issues, I tested it and leads to huge number calls in the component, and template rendering, specially if we have a lot of strings or change cycles in your app.

I did a similar solution with a pure pipe, with one more input in order to make it change in the language change: {{‘Hello’ | _:trans.lang}}

where _ is the pipe to call and trans.lang is a public variable of the translate service. In this case the translation will trigger only if the trans.lang changes to another language.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Angular 2 impure pipe vs directive performance - Stack Overflow
The pipe is an Impure pipe that can handle the translation and any async loading of text. The downside to this approach that...
Read more >
Angular Performance: Optimizing Expression Re-evaluation ...
A pure pipe is only re-evaluated when either the inputs or any of the arguments change. So how does this matter in our...
Read more >
Difference between Angular directives vs components - eduCBA
Guide to Angular directives vs components. Here we discuss the Angular directives vs components key differences with comparison table.
Read more >
Built-in directives - Angular
Use Angular's built-in directives to manage forms, lists, styles, and what users ... Attribute directives, Change the appearance or behavior of an element, ......
Read more >
Pipe vs Directive in Angular - Geekboots
Pipe vs Directive · A user creates/uses a directive that parses the input into a formatted currency string. · Pipes are for formatting...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found