Speeding up AngularJS 
@konpyu! 
html5minute! 
2014.8.22
自己紹介 
• KON Yuichi (@konpyu)! 
• Software Engineer in peace of cake! 
• Love Angular! 
• SNS note: AngularでClient構築
Frontend MV*
TodoMVC Benchmark 
http://vuejs.org/perf/
そもそも遅い
なぜか
2way data binding 
ViewModel View 
・js が保持するデータと HTML として画面に表示さ 
れる内容が双方向で自動的に連携 
・大規模なSPA, WebAppで実装コストを削減可
2way data binding 
よくあるFW 
→ 専用のクラスを継承して手動でBindingを設定 
AngularJS 
→ PureなJavascript ObjectをViewModelとして扱う 
$scope 
↑この方
2way data binding 
<p>{{ user.name }}</p> 
html
2way data binding 
<p>{{ user.name }}</p> 
$scope.user.name = “konpyu”; 
html 
js
2way data binding 
楽すぎる! 
<p>{{ user.name }}</p> 
$scope.user.name = “konpyu”; 
html 
js
2way data binding 
html 
<input type=“text” ng-model=“name”>
2way data binding 
html 
<input type=“text” ng-model=“name”>
2way data binding 
楽すぎる! 
<input type=“text” ng-model=“name”> 
alert($scope.name); 
html 
js
Dirty Checking 
$scopeはPureなjavascript object 
→ 値に何らかの変更があったかは言語の機能では検出 
できない 
→ Object.observe() はよ! 
! 
Angularでは… 
特定のタイミングで$scopeに変更があったか否かを 
$scopeの内容をすべて前後比較してチェック 
→ digest loopと呼ぶ
なので、方針としては 
1) 1回のdigest loopにかかる時間を減らそう 
2) digest loopが起こる回数を減らそう
dirty checkingの対象を減らそう 
変更あったで 
変更あったで 
digest loop 
対象が2000を超えると遅延が目立つと言われている 
http://stackoverflow.com/questions/9682092/databinding-in-angularjs/9693933#9693933
dirty checkingの対象を減らそう 
変更あったで 
変更あったで 
digest loop 
対象が2000を超えると遅延が目立つと言われている 
http://stackoverflow.com/questions/9682092/databinding-in-angularjs/9693933#9693933
one-time binding 
version 1.3では値の変更が無さそうなものは最初の1回 
しか評価しないように設定できる 
! 
余計な前後比較の数を減らせるので処理時間が減る 
- Official Doc 
https://docs.angularjs.org/guide/expression#one-time-binding
one-time binding
one-time binding 
変わる可能性アリ 
変わる可能性アリ
one-time binding 
多分変わらない 
多分変わらない 
多分変わらない
one-time binding 
one-time bindingにしたい変数の前に::を付けるだけ
bindonce 
・one-time bindingは1.3での実装 
・1.2系でも、同様のコンセプトのDirectiveがいくつか 
公開されている 
・Pasvaz/bindonce  
https://github.com/Pasvaz/bindonce
重たいFilter 
・Filterは便利だが、digest loopごとに計算されるので 
重たい処理を挟むと時間がかかる 
・Custom Filterを作る時は実行時間を意識する 
・どうしようもなければ事前計算する
digest loopが起こる回数を 
減らそう 
digest loopが起こるタイミング 
! 
1) DOMイベントが発生した時 
2) $html,$resourceでレスポンスが返ってきた時 
3) $locationで遷移が行われる時 
4) $timeoutで指定秒が経った時
$timeoutは必要? 
・$timeoutはsetTimeoutのwrapper 
・setTimeoutとの違いは、tick時にdigest loopが走るか 
・tick時に$scopeの変更がないのであれば、setTimeoutにした 
方が余計なdigest loopが走らない 
・もしくは、$timeoutの第三引数にfalseをsetするとdigest loop 
が走らない 
← (例)10s後にPVを加算するAPIを 
call。tick時にDOMの書き換えは無 
くdigest loopを走らせる必要がな 
いので第三引数をfalseにしてskip
API Callはなるべく1本に 
・当たり前といえば当たり前だが… 
・$http, $resourceでデータをfetchした時にdigest loop 
が走るため、画面構築時に何本もAPIを呼ぶとdigest loop 
が多く走ってしまう
まとめ 
・Angularの2way data bindingはPureなJS Objectが 
ViewModelになります 
・PureなJS Objectに変化があったか否かは現状のjsの仕様では 
検知できないので、無理やり前後比較をします(Dirty 
Checking) 
・watch対象が増えるとdigest loopにかかる時間が増えて重く 
なります 
・digest loopにかかる時間と、発生頻度を減らす事が高速化の 
基本方針です

AngularJSの高速化