Skip to content

Commit 6532171

Browse files
committed
feat(docs): document code size management tools for Dart
1 parent b9cf945 commit 6532171

File tree

2 files changed

+141
-0
lines changed

2 files changed

+141
-0
lines changed

TOOLS.md

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Developer Tools for Angular 2
2+
3+
- JavaScript (TBD)
4+
- [Dart](TOOLS_DART.md)

TOOLS_DART.md

+137
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
# Developer Tools for Dart
2+
3+
Here you will find a collection of tools and tips for keeping your application
4+
perform well and contain fewer bugs.
5+
6+
## Code size
7+
8+
Code needs to be downloaded, parsed and executed. Too much code could lead to
9+
slow application start-up time, especially on slow networks and low-end devices.
10+
The tools below will help you identify contributors to code size and keep them
11+
in check.
12+
13+
### Finding contributors to code size
14+
15+
#### --dump-info
16+
17+
`dart2js` has an option `--dump-info` that outputs information about what
18+
happened during compilation. Enable this option in your transformer options
19+
like this:
20+
21+
```yaml
22+
transformers:
23+
...
24+
- $dart2js:
25+
commandLineOptions:
26+
- --dump-info
27+
```
28+
29+
Use the [visualizer](https://github.com/dart-lang/dump-info-visualizer) to
30+
analyze the output or any of the command-line tools documented
31+
[here](http://dart-lang.github.io/dart2js_info/doc/api/index.html).
32+
33+
#### ng2soyc.dart
34+
35+
[ng2soyc](https://github.com/angular/ng2soyc.dart) is a utility for analyzing
36+
code size contributors in Angular 2 applications. It groups code size by
37+
library. It also assumes your library names follow
38+
"package.library.sub-library..." convention and gives code size breakdown at
39+
each level. To reduce noise in the output (for very large apps) it also provides
40+
an option to hide libraries that are too small, so you can focus on the biggest
41+
contributors.
42+
43+
#### Use code coverage to find dead code
44+
45+
When running in Dartium (or in Dart VM in general) you can request code
46+
coverage information from the VM. You can either use
47+
[observatory](https://www.dartlang.org/tools/observatory/), or download
48+
the coverage file and use your own tools to inspect it. Lines of code that are
49+
not covered are top candidates for dead code.
50+
51+
Keep in mind, however, that uncovered code is not sufficient evidence of dead
52+
code, only necessary evidence. It is perfectly possible that you simply didn't
53+
exercise your application in a way that triggers the execution of uncovered
54+
code. A common example is error handling code. Just because your testing never
55+
encountered an error does not mean the error won't happen in production. You
56+
therefore do not have to rush and remove all the `catch` blocks.
57+
58+
### Reducing code size
59+
60+
#### Disable reflection
61+
62+
`dart:mirrors` allows discovering program metadata at runtime. However, this
63+
means that `dart2js` needs to retain that metadata and thus increase the size
64+
of resulting JS output. In practice, however, it is possible to extract most
65+
metadata necessary for your metaprogramming tasks statically using a
66+
transformer and `package:analyzer`, and act on it before compiling to JS.
67+
68+
#### Enable minification
69+
70+
Minification shortens all your `longMethodNames` into 2- or 3-letter long
71+
symbols. `dart2js` ensures that this kind of renaming is done safely, without
72+
breaking the functionality of your programs. You can enable it in `pubspec.yaml`
73+
under `$dart2js` transformer:
74+
75+
```yaml
76+
transformers:
77+
...
78+
- $dart2js:
79+
minify: true
80+
```
81+
82+
#### Manually remove dead code
83+
84+
`dart2js` comes with dead code elimination out-of-the-box. However, it may not
85+
always be able to tell if a piece of code could be used. Consider the following
86+
example:
87+
88+
```dart
89+
/// This function decides which serialization format to use
90+
void setupSerializers() {
91+
if (server.doYouSupportProtocolBuffers()) {
92+
useProtobufSerializaers();
93+
} else {
94+
useJsonSerializaers();
95+
}
96+
}
97+
```
98+
99+
In this example the application asks the server what kind of serialization
100+
format it uses and dynamically chooses one or the other. `dart2js` could never
101+
tell whether the server responds with yes or no and so it must retain both
102+
kinds of serializers. However, you, as the developer of the application, may
103+
know in advance that your server supports protocol buffers and so you could
104+
remove that `if` block entirely and default to protocol buffers.
105+
106+
Code coverage (see above) is a good way to find dead code in your app.
107+
108+
#### Unsafe options
109+
110+
Dart also provides more aggressive optimization options. However, you have to
111+
be careful when using them and as of today the benefits aren't that clear. If
112+
your type annotations are inaccurate you may end up with non-Darty runtime
113+
behavior, including the classic "undefined is not a function" tautology, as
114+
well as the "keep on truckin'" behavior, e.g. `null + 1 == 1` and
115+
`{} + [] == 0`.
116+
117+
`--trust-type-annotations` tells `dart2js` to trust that your type annotations
118+
are correct. So if you have a function `foo(Bar bar)` the compiler can omit the
119+
check that `bar` is truly `Bar` when calling methods on it.
120+
121+
`--trust-primitives` tells `dart2js` that primitive types, such as numbers and
122+
booleans are never `null` when performing arithmetic, and that your program
123+
does not run into range error when operating on lists, letting the compiler
124+
remove some of the error checking code.
125+
126+
These options are specified in `pubspec.yaml`.
127+
128+
Example:
129+
130+
```yaml
131+
transformers:
132+
...
133+
- $dart2js:
134+
commandLineOptions:
135+
- --trust-type-annotations
136+
- --trust-primitives
137+
```

0 commit comments

Comments
 (0)