Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
ngUpgradeと移植戦略
Search
OKUNOKENTARO
March 21, 2016
Programming
4.2k
6
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
ngUpgradeと移植戦略
2016/3/21 ng-japan 2016の登壇に使用した資料です。
OKUNOKENTARO
March 21, 2016
More Decks by OKUNOKENTARO
See All by OKUNOKENTARO
トレタO/X アーキテクチャ移行記 Next.js App Router化への道のり / TORETA TECH UPDATE 1
okunokentaro
5
12k
Podcastを継続する技術 / refactoradio-240119
okunokentaro
1
220
Webアプリケーション設計の第一歩は ディレクトリの整理から / Encraft 1
okunokentaro
33
10k
JSONとJSON Schemaを改めて理解する / tokyo_study
okunokentaro
9
2.5k
それでもどうしてRecoilを使うのか / Harajuku.ts Meetup Recoil
okunokentaro
19
5.7k
TypeScriptは10年でこんなに進化しました / TechFeed Experts Night 11
okunokentaro
6
1.8k
Hasura.io RDBをサクサク作る方法はARやO/RMだけじゃなくなりました/hasura-io
okunokentaro
5
730
コードには型アノテーションよりも要件アノテーションを増やせ!/harajukuts2
okunokentaro
14
6.6k
10年と3ヶ月でWebサービスを作った話 / Piyogrammer Conference 2021
okunokentaro
2
1.1k
Other Decks in Programming
See All in Programming
Laravelのアプリケーションをどこにデプロイするか #ツナギメオフライン.9
akase244
0
120
思考垂れ流し開発 ~音声入力 × AIエージェント × 開発ハーネスによる試行錯誤~
npostring
0
1.1k
ALB ログから Trace を気合で繋げる技術
fohte
7
880
ゲームコントローラやキーボードのファームウェアをSwiftで書く
kishikawakatsumi
1
210
MIZARU@SPAJAM2026 第二回予選
1901drama
0
110
AI × TiDD / 2026.09.05 Redmine 大阪
tokudiro
1
120
DroidKaigi 2026 「個人開発という実験場: Android エンジニアが手にする4つの自由」
slashnephy
0
230
AGENTS.md Is Not Enough:Build Skills, Don't Download Them
lx_t
0
110
Deep dive into the select statement (GopherCon UK)
jespino
0
170
「AI時代、配布するPythonコードをどう守るか: 難読化の実験と判断軸」 #PyconJP2026
pkshadeck
PRO
2
200
Swift愛好会100回記念 第1回を振り返る
jollyjoester
0
120
高専キャリア LT 発表内容
crysta1221
6
5.7k
Featured
See All Featured
The Art of Programming - Codeland 2020
erikaheidi
57
14k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
230
23k
Navigating Weather and Climate Data
rabernat
0
510
My Coaching Mixtape
mlcsv
0
310
How GitHub (no longer) Works
holman
316
150k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
234
17k
Prompt Engineering for Job Search
mfonobong
0
450
Leveraging Curiosity to Care for An Aging Population
cassininazir
1
490
BBQ
matthewcrist
89
10k
Conquering PDFs: document understanding beyond plain text
inesmontani
PRO
4
3k
The Director’s Chair: Orchestrating AI for Truly Effective Learning
tmiket
1
300
Redefining SEO in the New Era of Traffic Generation
szymonslowik
1
410
Transcript
ngUpgradeと移植戦略 Mar 21, 2016 / ng-japan armorik83
はちさん 奥野 賢太郎 @armorik83 ng-kyoto代表 ChatWork株式会社
Qiita
ng-kyoto 4/10 渋谷ヒカリエ by teratail / ng-kyoto, ng-japan 4/16 サイボウズ大阪梅田オフィス
/ ng-kyoto, GDG神戸 ng-kyoto Angular 2ハンズオン勉強会 東西合同開催!!
お話しすること • なぜ移行戦略ではなく移植戦略なのか • 移植の前に現在地を知る • 移植の複数のフェーズ • Angular 1のこれって2ではどう書くの?
なぜ移行戦略ではなく 移植戦略なのか
その前に前提 • 業務としてAngular 2化を進めている上での知見 • 1と2は全く互換性のない同名の別フレームワーク というのは誤解 • UPGRADING FROM
1.X https://angular.io/docs/ts/latest/guide/upgrade.html • Angular 1から2へは移行可能
なのになぜ移植と呼ぶか • すべての手順を公式サイトの通りに進めるのは煩雑 • 世界中のAngularのコーディング・スタイルはバラバラ • 「ドキュメント通りに移行しなければ」と悩むより Angular 2流儀を覚えてイチから書いたほうが むしろ早い可能性もある
とはいえ移植はしんどい! • これを全て移植するのか…と憂鬱になる • できることなら移行したい • 楽に移行したい
段階的移植法 • 段階的移植法(armorik83命名) • 公式サイトの移行手順は活かしながら ある程度は移植(書き直し)する • 移行を複数のフェーズで捉える • 少しずつ移植を進めて
最終的には全てがAngular 2な状態へ
移植の前に現在地を知る
現在地はどこだ TypeScript Angular 2 ES2015 ES5 Coffee Script AngularJS 1.4,
1.5 1.3 1.2
TypeScript Angular 2 ES2015 ES5 Coffee Script AngularJS 1.4, 1.5
1.3 1.2 この距離で 移植難度が異なる 現在地はどこだ
言語をどうするか • CoffeeScriptが最も遠く TypeScriptが最も近い • ES5, ES2015の場合 「--allowJsを付けてJS, TSを混ぜてコンパイル」でも 動くので段階的TypeScript化でなんとかなる
• Angular 2はTypeScript専用ではないので ES5でも扱える
Angular 1.xのバージョン • 最新にするに越したことはない • 1.2を使っている場合 残念ながら移行への道のりは険しい • 一旦1.5まで移行してから2への段階的移植を 試みたほうがよい(もしくは諦める)
• 1.4を使っている場合 1.4 → 1.5は楽なのでまず1.5にして2化に備えておく
いまAngular 1をどう書くか • 手前味噌ですがAngularJSモダンプラクティスは 現在も有効 http://qiita.com/armorik83/items/5542daed0c408cb9f605 • AngularJS老化チェックの記事で現在のプロダクトの 老化度を測り若返らせる(1.5に寄せていく) http://qiita.com/laco0416/items/edfa917583af4593ad6c
1.5 Componentにすべきか • Angular 1.5から追加された angular.module().component() • 1.4までのDirectiveは1.5のComponentに 一旦移行してからAngular 2化すべきか?
1.5でのDirectiveの扱い • 現在のプロダクトで無理にDirectiveとComponentを 両方を混ぜる必要はない(好みの話) • 無理にすべて移行する必要も無い • ただしDirectiveを構造的に細分化しているなら不要だが そこの考慮が無い場合一旦Componentにしていくとよい •
$scopeを多用している場合、先にComponent化すべき • Angular 1.5を今から新しく始めるならば 最初からComponentを使うべき
移植の複数のフェーズ
移植戦略マップ TypeScript Angular 2 ES2015 ES5 Coffee Script AngularJS 1.4,
1.5 1.3 1.2 この箇所を細分化する
複数のフェーズ 1. 準備 2. ng2 Component作成 3. ng1 ServiceのUpgrade 4.
ng2 Componentへの機能移植 5. ng1 Serviceのng2 Service化 6. Router周り、bootstrap周りの移植
1. 準備 • 幾つものUIパーツで構成されるWebアプリケーションを想定 • チーム内で合意を得る、稟議を通す 稟議の通し方は様々だが、パフォーマンス改善は説得力ある • キャッチアップの社内勉強会、外部の勉強会に参加 •
branchを分ける、依存関係の修正 ビルド環境の調整など足回りを組み立てる • 一度Angular 2チュートリアルでミニアプリ開発を 試しておくと吉
2. ng2 Component作成 app-main app-nav app-contents app-nav-items app-contents-body ng1 Directiveと同要素名でng2
Componentを作成 とにかくガワを作る まだマウスやウインドウのイベント・ハンドリング移植はしない ng-ifやng-repeatは、ここで*ngIfや*ngForに書き直す app-main app-nav app-contents app-nav-items app-contents-body app-root
2. ng2 Component作成 ルートだけはng1 Directiveで そこに連なる要素をすべてng2 Componentにする ルートに置くng2 Componentを upgradeAdapter.downgradeNg2Component()でng1でも利用できるよう変換
app-main-ng2 app-nav app-contents app-nav-items app-contents-body app-root 変換 ng1の世界 ng2の世界
2. ng2 Component作成 テンプレートからng-appを除去 angular.bootstrap()形式にリファクタリングしておく さらにupgradeAdapter.bootstrap()に書き直すとng1内でng2を扱える app-main-ng2 app-nav app-contents app-nav-items
app-contents-body app-root 変換 ng1の世界 ng2の世界
3. ng1 ServiceのUpgrade • ng1 ServiceをupgradeAdapter.upgradeNg1Provider()に通して ng2で利用可能な状態にする • ng2 Componentにng1
ServiceをDIする • コードの書き方を詳細に話すと時間がないので割愛 • UPGRADING FROM 1.X https://angular.io/docs/ts/latest/guide/upgrade.html
4. ng2 Componentへの機能移植 • 機能をng1 Directiveからng2 Componentへ移植していく • コピペでいけるものもあるが、書き直す必要がある箇所もある •
ng1 Directiveにロジックをベタッと書かず あらかじめng1 Serviceから利用する形にしておくと だいぶこのフェーズは楽になる • ng2 ServiceはupgradeAdapter.bootstrap()で起動する 前にupgradeAdapter.addProvider()で登録しておく
ng1 Serviceをng2 Serviceに移植する 移植作業中はng2 Componentからng1 Serviceを使っておく 5. ng1 Serviceのng2 Service化
app-main-ng2 app-nav app-contents app-nav-items app-contents-body app-root Ng1APIService Ng1StorageService Ng2APIService 裏で移植作業 Ng2StorageService
必要な移植作業が終わったらng1 Serviceはお役御免となる app-main-ng2 app-nav app-contents app-nav-items app-contents-body app-root Ng1APIService Ng1StorageService
Ng2APIService 移植できた Ng2StorageService 5. ng1 Serviceのng2 Service化
ng2 Service化できたらng1 Serviceをng2 Serviceに付け替える テストで切り替え前後の挙動に変化が無いか担保できるとよし 最悪目視・手動操作で確認 app-main-ng2 app-nav app-contents app-nav-items
app-contents-body app-root Ng2APIService ng2化 Ng2StorageService 5. ng1 Serviceのng2 Service化
app-main app-nav app-contents app-nav-items app-contents-body app-root 6. Router周り、bootstrap周りの移植 ルート要素もng2化、アダプタを用いた接合部分もアダプタを外す ui-routerやbootstrap周りもAngular
2に移植 おそらくけっこう大変なフェーズ(うちもまだ辿り着いていない) app-main-ng2 app-nav app-contents app-nav-items app-contents-body app-root
Angular 1のこれって 2ではどう書くの?
Filterの使用 ng1 <td>{{movie.title | uppercase}}</td> ng2 <td>{{movie.title | uppercase}}</td> Angular
2ではFilterのことをPipeと呼ぶ Angular 1 to 2 Quick Refを読めば対応が表にまとめられているので必読 https://angular.io/docs/ts/latest/cookbook/a1-a2-quick-reference.html
Filterの定義 ng1 angular.module().filter("reverse", function(){}); ng2 @Pipe({name: "reverse"}) export class FilterPipe
implements PipeTransform { transform(value: string): string { return // } } Pipe Annotationを付けたclassにtransform()メソッドを実装する
Serviceの定義 ng1 angular.module().service("Service", function(){}); ng2 @Injectable() export class Service {
// } bootstrap(RootComponent, [Service]); Injectable Annotationを付けたclassをbootstrap第二引数に渡す または、DIしたいComponentのprovidersプロパティに渡す
イベントのハンドリング ng1 $element[0].addEventListener("mouseenter", function(){ this.color = "#0000ff"; $scope.$apply(); }); ng2
@HostListener("mouseenter", ["$event"]) onMouseenter($event: MouseEvent) { this.color = "#0000ff"; } 自身のイベントをハンドリングするなら @HostListener()をメソッドに付ける
$apply ng1 $scope.$apply(); ng2 ChangeDetectorRef.detectChanges() Zonesのお陰で基本的に手動での変更検知発火は不要 どうしても手動で再bindを走らせたいときは ChangeDetectorRefをDIし、detectChanges()を呼ぶ
$watch ng1 $scope.$watch("name", function(newVal, oldVal) { // }); ng2 ngOnChanges(changes)
{ console.log(changes["name"].currentValue); } ngOnChanges()にて可能
$watchCollection ng1 $scope.$watchCollection("obj", function(newObj, oldObj) { // }); ng2 ngDoCheck()
{ const changes = this.differ.diff(this.list); if (changes) { // } } 配列ならばIterableDiffers、オブジェクトならばKeyValueDiffersを用いて ngDoCheck()内で差分を検出することで可能 準備が面倒な上に処理負荷が大きめなので極力ngOnChanges()で済ませたい
One-time Binding ng1 {{::param}} ng2 @Component({ selector: "my-component", changeDetection: ChangeDetectionStrategy.OnPush,
template: `{{param}}` }) ChangeDetectionStrategy.OnPushを指定する その中で手動で再bindしたいときは ChangeDetectorRef.markForCheck()を呼ぶ
compile, link, destroy • ng1 DirectiveのlinkはngOnInit(), ngAfterViewInit()などの Lifecycle Hooksで代替可能 https://angular.io/docs/ts/latest/guide/lifecycle-hooks.html
• $scope.$on("$destroy")はLifecycle HooksのngOnDestroy() で代替可能 • ng1 Directiveのcompileプロパティで行っていたフックは ng2 Componentでは代替不可 • ngOnInit()で近いことはできる jQueryを使って別要素を生成していたりすると移植困難
まとめ
なんとかなる
ありがとうございました ngUpgradeと移植戦略