Search code examples
angulartypescriptherokujhipstermaven-frontend-plugin

Missing component in Angular when it has service mentioned in constructor, non used inside the component itself. JHipster app


Here what we have in browser's debug:

const Mp = {
        pageTitle: "ученику"
    }
      , Ap = {
        path: "to-student",
        component: Fp,
        data: Mp,
        canActivate: [m.b]
    };
    class Dp {
        constructor() {}
        ngOnInit() {}
    }

enter image description here

It is interesting, that with npm start it is compiled well and fails in runtime only when it is built with npm plugin of maven on production side (heroku).

At the module we have:

import {
  BlogDocumentsComponent,
  BlogFaqComponent,
  BlogEntriesComponent,
  ShopComponent,
  ShopSuccessComponent,
  ShopFailureComponent,
  SyllablesComponent,
  RedirectComponent,  
  //  UsefulStuffComponent actually not there
} from './';

import 'd3';
import 'nvd3';
import { NvD3Module } from 'ng2-nvd3';
import { UsefulStuffComponent } from './useful-stuff/useful-stuff.component';

so UsefulStuffComponent is not in common import, but its path is correct!

And it is not mentioned in the corresponding index.ts of the module (we don't need it ever, if the full path is set, right?)

So the problem can be fixed by explicitly making UsefulStuffComponent be exported in index.ts and being exported with other component the same way:

import {
  BlogDocumentsComponent,
  BlogFaqComponent,
  BlogEntriesComponent,
  ShopComponent,
  ShopSuccessComponent,
  ShopFailureComponent,
  SyllablesComponent,
  RedirectComponent,  
  UsefulStuffComponent actually not there
} from './';

import 'd3';
import 'nvd3';
import { NvD3Module } from 'ng2-nvd3';
//  import { UsefulStuffComponent } from './useful-stuff/useful-stuff.component'; actually no import here

So, why I'm getting this kind of production runtime failure, but never get it on npm start locally?

UPD:

So, after the advice of @Gaël Marziou I have tried to localize the change that made the component to be lost at prod state. I have reveal that this component still causes the prod error:

import { Component, OnInit } from '@angular/core';
import { filter, map } from 'rxjs/operators';
import { HttpErrorResponse, HttpResponse } from '@angular/common/http';
import { PaymentService } from 'app/businesslogic';
import { JhiAlertService } from 'ng-jhipster';
import { IAccessSubscription } from 'app/shared/model/access-subscription.model';
import { AccessSubscriptionService } from 'app/entities/access-subscription';

@Component({
  templateUrl: './to-student.component.html',
  styleUrls: ['./to-student.component.scss']
})
export class ToStudentComponent implements OnInit {
  accessSubscriptions: IAccessSubscription[] = [];
  accessSubscriptionsIds: number[] = [];

  constructor(
    protected jhiAlertService: JhiAlertService,
    protected accessSubscriptionsService: AccessSubscriptionService,
    protected paymentService: PaymentService
  ) {}

  ngOnInit() {
    this.loadAll();
  }

  loadAll() {
    this.accessSubscriptionsService
      .queryAllMine()
      .pipe(
        filter((mayBeOk: HttpResponse<IAccessSubscription[]>) => mayBeOk.ok),
        map((response: HttpResponse<IAccessSubscription[]>) => response.body)
      )
      .subscribe(
        (res: IAccessSubscription[]) => {
          this.accessSubscriptions = res;
          this.accessSubscriptions.map((item: IAccessSubscription) => {
            this.accessSubscriptionsIds.push(item.id);
          });
        },
        (res: HttpErrorResponse) => this.onError(res.message)
      );
  }

  protected onError(errorMessage: string) {
    this.jhiAlertService.error(errorMessage, null, null);
  }
}

while this one already works well:

import { Component, OnInit } from '@angular/core';
import { filter, map } from 'rxjs/operators';
import { HttpErrorResponse, HttpResponse } from '@angular/common/http';
import { PaymentService } from 'app/businesslogic';
import { JhiAlertService } from 'ng-jhipster';
import { IAccessSubscription } from 'app/shared/model/access-subscription.model';
import { AccessSubscriptionService } from 'app/entities/access-subscription';

@Component({
  templateUrl: './to-student.component.html',
  styleUrls: ['./to-student.component.scss']
})
export class ToStudentComponent implements OnInit {
  accessSubscriptions: IAccessSubscription[] = [];
  accessSubscriptionsIds: number[] = [];

  constructor(protected jhiAlertService: JhiAlertService, protected accessSubscriptionsService: AccessSubscriptionService) {}

  ngOnInit() {
    this.loadAll();
  }

  loadAll() {
    this.accessSubscriptionsService
      .queryAllMine()
      .pipe(
        filter((mayBeOk: HttpResponse<IAccessSubscription[]>) => mayBeOk.ok),
        map((response: HttpResponse<IAccessSubscription[]>) => response.body)
      )
      .subscribe(
        (res: IAccessSubscription[]) => {
          this.accessSubscriptions = res;
          this.accessSubscriptions.map((item: IAccessSubscription) => {
            this.accessSubscriptionsIds.push(item.id);
          });
        },
        (res: HttpErrorResponse) => this.onError(res.message)
      );
  }

  protected onError(errorMessage: string) {
    this.jhiAlertService.error(errorMessage, null, null);
  }
}

So, non-working just contains an import of some service in the constructor that isn't ever used:

   protected paymentService: PaymentService

Solution

  • Some Angular errors can really be difficult to debug especially when they don't appear in dev builds.

    Each time I faced such situation I actually rolled back my changes until I found the culprit commit.

    If you're doing it after lot of changes, you can use a script with git bisect to identify the faulty lines assuming your commits are small of course.

    Ideally, to avoid this "archaeological" search, you should put in place automatic continuous integration from beginning of your project, this way you are sure that deeper checkings from production builds will catch errors earlier.