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.

The result of code generated by ng build --prod is different from code generated by ng build

See original GitHub issue

Bug Report or Feature Request (mark with an x)

- [x] bug report -> please search issues before submitting
- [ ] feature request

Versions.

@angular/cli: 1.0.5 node: 6.10.3 os: darwin x64 @angular/common: 4.1.3 @angular/compiler: 4.1.3 @angular/core: 4.1.3 @angular/forms: 4.1.3 @angular/http: 4.1.3 @angular/platform-browser: 4.1.3 @angular/platform-browser-dynamic: 4.1.3 @angular/router: 4.1.3 @angular/cli: 1.0.5 @angular/compiler-cli: 4.1.3

Repro steps.

Both ng build and ng build --prod run without generating error messages. Everything seems OK but the code generated by ng build results in the display of 77 lines (as expected) while ng build --prod displays 1 line only.

The log given by the failure.

I didn’t modify the environment settings. There is no failure that I could see. Both seem to be compiling without issues.

ng build Hash: ea7b04b8a69e4a08f068 Time: 19641ms chunk {0} polyfills.bundle.js, polyfills.bundle.js.map (polyfills) 158 kB {5} [initial] [rendered] chunk {1} main.bundle.js, main.bundle.js.map (main) 821 kB {4} [initial] [rendered] chunk {2} styles.bundle.js, styles.bundle.js.map (styles) 147 kB {5} [initial] [rendered] chunk {3} scripts.bundle.js, scripts.bundle.js.map (scripts) 266 kB {5} [initial] [rendered] chunk {4} vendor.bundle.js, vendor.bundle.js.map (vendor) 2.92 MB [initial] [rendered] chunk {5} inline.bundle.js, inline.bundle.js.map (inline) 0 bytes [entry] [rendered]

ng build --prod Hash: 277f842cca1d5921283b Time: 31756ms chunk {0} polyfills.1577c7d212bc014644eb.bundle.js (polyfills) 158 kB {5} [initial] [rendered] chunk {1} main.c366c9602d2a66ca8dac.bundle.js (main) 965 kB {4} [initial] [rendered] chunk {2} scripts.c4fec663d6273ee04888.bundle.js (scripts) 266 kB {5} [initial] [rendered] chunk {3} styles.d96180d746287286ac7b.bundle.css (styles) 175 bytes {5} [initial] [rendered] chunk {4} vendor.314120fa29a6055b1439.bundle.js (vendor) 1.92 MB [initial] [rendered] chunk {5} inline.42b23acf2c594abf3fb5.bundle.js (inline) 0 bytes [entry] [rendered]

Desired functionality.

I was expecting the both (ng build and ng build --prod) would produce the same result during execution.

I’ve tried compiling with @angular/cli versions 1.02, 1.03, 1.04, and 1.05, and all versions produced the same result on mac and windows.

Mention any other details that might be useful.

Component that is producing this behavior:

import {Component, OnDestroy, OnInit} from ‘@angular/core’; import {Router, ActivatedRoute} from ‘@angular/router’; import {Subscription} from ‘rxjs/Subscription’;

import {BrandService} from ‘./brand.service’; import {Brand} from ‘./brand.model’; import {Series} from ‘./series/series.model’; import {SeriesService} from ‘./series/series.service’;

@Component({ selector: ‘app-brand’, templateUrl: ‘./brand.component.html’, styleUrls: [‘./brand.component.css’] }) export class BrandComponent implements OnInit, OnDestroy { selectedBrand: Brand; subscription: Subscription; selectedSeries: Series; serieses: Series[] = []; selectFirstOption = ‘Select a Series’;

constructor(private _router: Router, private _activatedRoute: ActivatedRoute, private _brandService: BrandService, private _seriesService: SeriesService) { }

ngOnInit() { this.getSelectedBrand(); this.getSerieses(this.selectedBrand); }

onSelectedSeries(): void { if (typeof this.selectedSeries === ‘object’) { this._seriesService.setSelectedSeries( this._seriesService.getSeriesByNameAndBrand( this.selectedSeries.name, this._brandService.getSelectedBrand() ) ); this._router.navigate([encodeURIComponent(this.selectedSeries.name)], {relativeTo: this._activatedRoute}) .then() .catch(); } else { this._router.navigate([‘.’], {relativeTo: this._activatedRoute}) .then() .catch(); } }

getSelectedBrand() { this.selectedBrand = this._brandService.getSelectedBrand(); this.subscription = this._brandService.selectedBrandChanged .subscribe( (brand: Brand) => { this.selectedBrand = brand; } ); }

getSerieses(selectedBrand: Brand) { this.serieses = this._seriesService.getSerieses(selectedBrand); }

ngOnDestroy() { this.subscription.unsubscribe(); } }

HTML template: <app-header></app-header>
<div class=“container-fluid”>
<div class=“row”>
<div class=“col-xs-12 col-md-12”>
<form class=“form-group” #f=“ngForm” novalidate>
<label>Series</label>
<select title=“Select a series” class=“selectpicker form-control” (change)=“onSelectedSeries()”
name=“selectForSeries”
[(ngModel)]=“selectedSeries”>
<option>{{selectFirstOption}}</option>
<option *ngFor=“let series of serieses” [ngValue]=“series”>{{series.name}}</option>
</select>
</form>
<hr>
<router-outlet></router-outlet>
</div>
</div>
</div>

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:8 (3 by maintainers)

github_iconTop GitHub Comments

3reactions
filipesilvacommented, Jul 14, 2017

Heya @lucianojardim, I’ve been looking at your code and think I’ve found the problem.

In the setSelected method inside selected.service.ts, you have this piece of code:

this._selectedType = Series.name;

Where Series is this class:

export class Series {
  id: number;
  name: string;
  brandId: number;

  constructor(id: number, name: string, brandId: number) {
    this.id = id;
    this.name = name;
    this.brandId = brandId;
  }
}

When you do Series.name you are not accessing the name property of a Series instance, but rather the name property of the class Series itself.

A class gets downleveled to a function in ES5, and functions do have the name property - it’s the name of the function itself. So in this case, it’s the string "Series".

A big part of uglification is name mangling, where function and variable names are converted to a shorter version. This yields significant size savings and is done on production builds.

This means that in production, Series.name is not "Series", but something else like "e". And this is how your code is breaking right now.

Code that relies on accessing a function’s name is not able to be uglifyied, and for that reason it is a good practice in the JS world to not rely on it. You can find that warning here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name

Warning: Be careful when using Function.name and source code transformations, such as those carried out by JavaScript compressors (minifiers) or obfuscators. These tools are often used as part of a JavaScript build pipeline to reduce the size of a program prior to deploying it to production. Such transformations often change a function's name at build-time.

My advice for getting around this is to set a static property with the string you need instead:

export class Series {
  static type = 'Series';
  id: number;
  name: string;
  brandId: number;

  constructor(id: number, name: string, brandId: number) {
    this.id = id;
    this.name = name;
    this.brandId = brandId;
  }
}

This way you can use Series.type instead of Series.name and it will not break on production builds.

1reaction
Simon-Briggscommented, May 25, 2017

https://github.com/angular/angular-cli/wiki/build#--dev-vs---prod-builds

If you don’t specify --prod the default build is --dev which doesn’t AOT compile or minify your app

Read more comments on GitHub >

github_iconTop Results From Across the Web

Differences between ng build and ng build --watch
ng build --prod does that. And the name of the generated files will be different as soon as you make a change, because...
Read more >
ng build - Angular
Option Description Value Type Default Value ‑‑aot Build using Ahead of Time compilation. boolean true ‑‑base‑href Base url for the application being built. string ‑‑delete‑output‑path Delete...
Read more >
Angular Dev vs Prod Build - Medium
Development build produces source map files whereas production builds not. Source map files help us easily debug our application even after the ...
Read more >
Deployment - Angular
Both ng build and ng serve clear the output folder before they build the project, but only the ng build command writes the...
Read more >
Angular dev build vs prod build - YouTube
To generate a development build we can use either ng build OR ng build --dev ... This is beacause with the production build...
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