95
votes

For some reason, I have to run my app in production mode. What is the difference between those modes?

2

2 Answers

79
votes

In development mode, change detection does a second run immediately after the first run and produces an error if any bound value has changed between the first and the second run. This helps to locate bugs where checking values has side-effects or fields or functions don't return the same value on subsequent calls which undermines Angular's change detection.

In development mode, during the second change detection run, Angular also does some deep object comparisons that it won't do in production to detect model changes that are disallowed.

Update:

In development mode, a hint is also printed to the console when the HTML sanitizer service strips values from bindings [innerHTML]="..." or [ngStyle]="...". See also: In RC.1 some styles can't be added using binding syntax

36
votes

The docs for ApplicationRef.tick() state:

In development mode, tick() also performs a second change detection cycle (TTL=2) to ensure that no further changes are detected. If additional changes are picked up during this second cycle, bindings in the app have side-effects that cannot be resolved in a single change detection pass. In this case, Angular throws an error, since an Angular application can only have one change detection pass during which all change detection must complete.

The reason that we can't have additional changes is because in production mode, change detection only runs once, which means that every component in the component tree is examined once (TTL=1)... from the top, in depth-first order. So if, e.g., a change to a child component's input property causes a change to some other property that the parent component has bound in a view/template, the parent component's view won't be updated (because change detection won't revisit the parent component in production mode... because of the "one pass" tree traversal). It will only get updated the next time some event happens and change detection runs again -- but that's too late!

Here's a Plunker that violates the rule – a child component has a set method on an input property that modifies another input property. Yes, it is a contrived example, but it is easier to understand than the next one:

Another scenario where you might run into this problem is with stateful pipes. Check out this answer if that's your problem.

You should describe your problem (in another SO question). There should be a way to fix it.