diff --git a/DEVELOPER.md b/DEVELOPER.md index 81058113cd..ac7e15f44f 100644 --- a/DEVELOPER.md +++ b/DEVELOPER.md @@ -1,7 +1,7 @@ -# Building and Testing Angular 2 for JS and Dart +# Building and Testing Angular 2 for JS -This document describes how to set up your development environment to build and test Angular, both -JS and Dart versions. It also explains the basic mechanics of using `git`, `node`, and `npm`. +This document describes how to set up your development environment to build and test Angular 2 JS version. +It also explains the basic mechanics of using `git`, `node`, and `npm`. * [Prerequisite Software](#prerequisite-software) * [Getting the Sources](#getting-the-sources) @@ -52,7 +52,7 @@ git remote add upstream https://github.com/angular/angular.git ``` ## Installing NPM Modules -Next, install the JavaScript modules and Dart packages needed to build and test Angular: +Next, install the JavaScript modules needed to build and test Angular: ```shell # Install Angular project dependencies (package.json) diff --git a/TOOLS.md b/TOOLS.md index 8b4b6b57c6..6f7dcf507c 100644 --- a/TOOLS.md +++ b/TOOLS.md @@ -1,4 +1,140 @@ # Developer Tools for Angular 2 -- [JavaScript](TOOLS_JS.md) -- [Dart](TOOLS_DART.md) +Here you will find a collection of tools and tips for keeping your application +perform well and contain fewer bugs. + +## Angular debug tools in the dev console + +Angular provides a set of debug tools that are accessible from any browser's +developer console. In Chrome the dev console can be accessed by pressing +Ctrl + Shift + j. + +### Enabling debug tools + +By default the debug tools are disabled. You can enable debug tools as follows: + +```typescript +import {enableDebugTools} from '@angular/platform-browser'; + +bootstrap(Application).then((appRef) => { + enableDebugTools(appRef); +}); +``` + +### Using debug tools + +In the browser open the developer console (Ctrl + Shift + j in Chrome). The +top level object is called `ng` and contains more specific tools inside it. + +Example: + +```javascript +ng.profiler.timeChangeDetection(); +``` + +## Performance + +### Change detection profiler + +If your application is janky (it misses frames) or is slow according to other +metrics it is important to find the root cause of the issue. Change detection +is a phase in Angular's lifecycle that detects changes in values that are +bound to UI, and if it finds a change it performs the corresponding UI update. +However, sometimes it is hard to tell if the slowness is due to the act of +computing the changes being slow, or due to the act of applying those changes +to the UI. For your application to be performant it is important that the +process of computing changes is very fast. For best results it should be under +3 milliseconds in order to leave room for the application logic, the UI updates +and browser's rendering pipeline to fit withing the 16 millisecond frame +(assuming the 60 FPS target frame rate). + +Change detection profiler repeatedly performs change detection without invoking +any user actions, such as clicking buttons or entering text in input fields. It +then computes the average amount of time it took to perform a single cycle of +change detection in milliseconds and prints it to the console. This number +depends on the current state of the UI. You will likely see different numbers +as you go from one screen in your application to another. + +#### Running the profiler + +Enable debug tools (see above), then in the dev console enter the following: + +```javascript +ng.profiler.timeChangeDetection(); +``` + +The results will be printed to the console. + +#### Recording CPU profile + +Pass `{record: true}` an argument: + +```javascript +ng.profiler.timeChangeDetection({record: true}); +``` + +Then open the "Profiles" tab. You will see the recorded profile titled +"Change Detection". In Chrome, if you record the profile repeatedly, all the +profiles will be nested under "Change Detection". + +#### Interpreting the numbers + +In a properly-designed application repeated attempts to detect changes without +any user actions should result in no changes to be applied on the UI. It is +also desirable to have the cost of a user action be proportional to the amount +of UI changes required. For example, popping up a menu with 5 items should be +vastly faster than rendering a table of 500 rows and 10 columns. Therefore, +change detection with no UI updates should be as fast as possible. Ideally the +number printed by the profiler should be well below the length of a single +animation frame (16ms). A good rule of thumb is to keep it under 3ms. + +#### Investigating slow change detection + +So you found a screen in your application on which the profiler reports a very +high number (i.e. >3ms). This is where a recorded CPU profile can help. Enable +recording while profiling: + +```javascript +ng.profiler.timeChangeDetection({record: true}); +``` + +Then look for hot spots using +[Chrome CPU profiler](https://developer.chrome.com/devtools/docs/cpu-profiling). + +#### Reducing change detection cost + +There are many reasons for slow change detection. To gain intuition about +possible causes it would help to understand how change detection works. Such a +discussion is outside the scope of this document (TODO link to docs), but here +are some key concepts in brief. + +By default Angular uses "dirty checking" mechanism for finding model changes. +This mechanism involves evaluating every bound expression that's active on the +UI. These usually include text interpolation via `{{expression}}` and property +bindings via `[prop]="expression"`. If any of the evaluated expressions are +costly to compute they could contribute to slow change detection. A good way to +speed things up is to use plain class fields in your expressions and avoid any +kinds of computation. Example: + +```typescript +@Component({ + template: '' +}) +class FancyButton { + // GOOD: no computation, just return the value + isEnabled: boolean; + + // BAD: computes the final value upon request + _title: String; + get title(): String { return this._title.trim().toUpperCase(); } +} +``` + +Most cases like these could be solved by precomputing the value and storing the +final value in a field. + +Angular also supports a second type of change detection - the "push" model. In +this model Angular does not poll your component for changes. Instead, the +component "tells" Angular when it changes and only then does Angular perform +the update. This model is suitable in situations when your data model uses +observable or immutable objects (also a discussion for another time). diff --git a/TOOLS_JS.md b/TOOLS_JS.md deleted file mode 100644 index 9d4aaa1abc..0000000000 --- a/TOOLS_JS.md +++ /dev/null @@ -1,140 +0,0 @@ -# Developer Tools for JavaScript - -Here you will find a collection of tools and tips for keeping your application -perform well and contain fewer bugs. - -## Angular debug tools in the dev console - -Angular provides a set of debug tools that are accessible from any browser's -developer console. In Chrome the dev console can be accessed by pressing -Ctrl + Shift + j. - -### Enabling debug tools - -By default the debug tools are disabled. You can enable debug tools as follows: - -```typescript -import {enableDebugTools} from '@angular/platform-browser'; - -bootstrap(Application).then((appRef) => { - enableDebugTools(appRef); -}); -``` - -### Using debug tools - -In the browser open the developer console (Ctrl + Shift + j in Chrome). The -top level object is called `ng` and contains more specific tools inside it. - -Example: - -```javascript -ng.profiler.timeChangeDetection(); -``` - -## Performance - -### Change detection profiler - -If your application is janky (it misses frames) or is slow according to other -metrics it is important to find the root cause of the issue. Change detection -is a phase in Angular's lifecycle that detects changes in values that are -bound to UI, and if it finds a change it performs the corresponding UI update. -However, sometimes it is hard to tell if the slowness is due to the act of -computing the changes being slow, or due to the act of applying those changes -to the UI. For your application to be performant it is important that the -process of computing changes is very fast. For best results it should be under -3 milliseconds in order to leave room for the application logic, the UI updates -and browser's rendering pipeline to fit withing the 16 millisecond frame -(assuming the 60 FPS target frame rate). - -Change detection profiler repeatedly performs change detection without invoking -any user actions, such as clicking buttons or entering text in input fields. It -then computes the average amount of time it took to perform a single cycle of -change detection in milliseconds and prints it to the console. This number -depends on the current state of the UI. You will likely see different numbers -as you go from one screen in your application to another. - -#### Running the profiler - -Enable debug tools (see above), then in the dev console enter the following: - -```javascript -ng.profiler.timeChangeDetection(); -``` - -The results will be printed to the console. - -#### Recording CPU profile - -Pass `{record: true}` an argument: - -```javascript -ng.profiler.timeChangeDetection({record: true}); -``` - -Then open the "Profiles" tab. You will see the recorded profile titled -"Change Detection". In Chrome, if you record the profile repeatedly, all the -profiles will be nested under "Change Detection". - -#### Interpreting the numbers - -In a properly-designed application repeated attempts to detect changes without -any user actions should result in no changes to be applied on the UI. It is -also desirable to have the cost of a user action be proportional to the amount -of UI changes required. For example, popping up a menu with 5 items should be -vastly faster than rendering a table of 500 rows and 10 columns. Therefore, -change detection with no UI updates should be as fast as possible. Ideally the -number printed by the profiler should be well below the length of a single -animation frame (16ms). A good rule of thumb is to keep it under 3ms. - -#### Investigating slow change detection - -So you found a screen in your application on which the profiler reports a very -high number (i.e. >3ms). This is where a recorded CPU profile can help. Enable -recording while profiling: - -```javascript -ng.profiler.timeChangeDetection({record: true}); -``` - -Then look for hot spots using -[Chrome CPU profiler](https://developer.chrome.com/devtools/docs/cpu-profiling). - -#### Reducing change detection cost - -There are many reasons for slow change detection. To gain intuition about -possible causes it would help to understand how change detection works. Such a -discussion is outside the scope of this document (TODO link to docs), but here -are some key concepts in brief. - -By default Angular uses "dirty checking" mechanism for finding model changes. -This mechanism involves evaluating every bound expression that's active on the -UI. These usually include text interpolation via `{{expression}}` and property -bindings via `[prop]="expression"`. If any of the evaluated expressions are -costly to compute they could contribute to slow change detection. A good way to -speed things up is to use plain class fields in your expressions and avoid any -kinds of computation. Example: - -```typescript -@Component({ - template: '' -}) -class FancyButton { - // GOOD: no computation, just return the value - isEnabled: boolean; - - // BAD: computes the final value upon request - _title: String; - get title(): String { return this._title.trim().toUpperCase(); } -} -``` - -Most cases like these could be solved by precomputing the value and storing the -final value in a field. - -Angular also supports a second type of change detection - the "push" model. In -this model Angular does not poll your component for changes. Instead, the -component "tells" Angular when it changes and only then does Angular perform -the update. This model is suitable in situations when your data model uses -observable or immutable objects (also a discussion for another time).