Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Speaker Deck
PRO
Sign in
Sign up for free
大規模改修の裏でTypeScriptとテスト導入をすすめた話
Amon Keishima
June 05, 2020
Programming
12
7.3k
大規模改修の裏でTypeScriptとテスト導入をすすめた話
Amon Keishima
June 05, 2020
Tweet
Share
Other Decks in Programming
See All in Programming
Scaling Productivity- How we have improved our dev experience
sockeqwe
1
120
MLOps勉強会_20220810
strsaito
0
210
Pluggable Storage in PostgreSQL
sira
1
190
このタイミングで知っておきたい 開発生産性の高いエンジニア組織の特徴とは / dev-sumi-20220721-productivity-features
findyinc
7
2.6k
RustのWebフレームワーク周りの概観
hayao
0
180
WindowsコンテナDojo: 第4回 Red Hat OpenShift Localを使ってみよう
oniak3ibm
PRO
0
180
僕が便利だと感じる Snow Monkey の特徴/20220723_Gifu_WordPress_Meetup
oleindesign
0
110
2022年のモダンCSS改
tonkotsuboy_com
24
16k
Getting Started With Data Structures
adoranwodo
1
260
Efficient UI testing in Android
alexzhukovich
1
120
Edge Side Frontend という新領域
mizchi
22
10k
VIMRC 2022
achimnol
0
130
Featured
See All Featured
A better future with KSS
kneath
226
16k
Facilitating Awesome Meetings
lara
29
4.1k
jQuery: Nuts, Bolts and Bling
dougneiner
56
6.4k
KATA
mclloyd
7
8.8k
The Illustrated Children's Guide to Kubernetes
chrisshort
18
40k
The Mythical Team-Month
searls
210
39k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
316
19k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
29
4.4k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
119
28k
Building Applications with DynamoDB
mza
84
4.8k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
224
49k
How GitHub Uses GitHub to Build GitHub
holman
465
280k
Transcript
⼤規模改修の裏で TypeScriptとテスト導⼊をすすめた話 LINE Growth Technology株式会社 UITチーム けいしま あもん
⾃⼰紹介 名前 Twitter @pittanko_pta 所属 LINE Growth Technology株式会社 UITチーム (けいしま
あもん) 慶島亜⾨
今⽇お話すること 担当しているLINEポイントクラブで メインタスクの合間をぬってTypeScriptやテストの導⼊をしている話 現状 作戦 やったこと 知⾒やハマり の順でお話していく
LINEポイントクラブとは 過去6ヶ⽉間に獲得した「LINEポイント」の総量に応じて決まる 4段階の「マイランク」ごとに、毎⽉LINEの各種サービスが お得に利⽤できる、様々な特典を受けられるプログラム 「LINEポイント」は 「LINE」の各種サービスの利⽤や、LINE公式アカウントの 友だち追加、動画視聴などで貯めることができる 前⾝はLINEフリーコインと呼ばれるもので LINEの中でも⻑く続いているサービスのひとつ ・実はWebベース
・Vue.jsで作られている
現状
プロジェクトが抱えていた問題点 2013年にスタートしたサービスであるため… テストコードが書かれていない ・Karmaが導⼊だけされているものの、テストコードがない ・しかし、リリースの度にQAを⾏うので品質は担保できていた いろんな環境が古い ・Webpackのバージョンが古い ・Babelのバージョンが古い サブプロジェクトとメインプロジェクトのビルド環境が違う ・Browserifyでビルドしている(gruntも使ってた)
・module.exports / requireを使っており import / export ではない QA: Quality Assuranceのこと
⻑期的にその問題点を考える 今まで⻑くやってきたプロジェクトなので仕⽅ない⾯もありますが 今後も⻑く続いていくだろうことを考えると… 新しく⼊ってくるメンバーが古い技術を勉強することよりも モダンな技術の知識で 即戦⼒になれるような環境 を整備するべきと考えた
問題点を解決するために… ・TypeScriptを導⼊すること ・テストを本格的に導⼊すること の2点はマストだと考えた
TypeScriptへのモチベーション コードに型がつくことで潜在的なミスを減らすことができる ・ビルドをする段階でミスに気づけるので、サービスの品質向上につながる ・コードレビューの負荷を軽減(しょうもないミスは事前に解決できそう)
テスト導⼊へのモチベーション 今後やりたいコードのリファクタリングを安⼼して⾏いたい ⼩さいバグを減らすことができれば、QAのコストも下がるかも
作戦
短期・中⻑期的な話 古いプロジェクトで機能追加案件も並⾏する場合 TSを導⼊して、テストを導⼊するのは時間がかかってしまうもの その中で早期に環境を整え、運⽤に組み込み基盤を作るのがプロジェクトでの最⼤の課題 そのために必要なのは、中⻑期を⾒据えた上での作戦(計画)を⽴てることだと思う 短期でTS運⽤基盤を構築することと、 中⻑期でのプロジェクトに適応させていくことが⼤きな鍵といえる 今回はまず、短期でのTS運⽤基盤の構築に注⼒した
作戦 TypeScriptの環境を導⼊ / Vue.js の TypeScript対応 Jestの導⼊ / Babelのアップデート /
Webpackのアップデート 脱Browserify / 脱grunt など… やりたいこと(やらないといけないこと)はたくさんあるが、 ⼀気にいろいろ変えてしまうとコードの差分が⼤きくなってしまう 動作を確認するにも時間かかるし レビュワーの負担も⼤きくなってしまう 今回の作戦は なるべく⼩さく⼊れること とした
(余談)社内の他案件の状況や傾向 LINEとしては2017年の上半期からTypeScriptの対応をリードエンジニアが始めている 新規に開発するプロジェクトではTypeScriptの採⽤に積極的な⼀⽅で 古くから存在するプロジェクトでは導⼊が遅れているようなものもある TypeScript導⼊済みのプロジェクトを⾒てみると… 社内サービスやSDKといった 社内で閉じたもの や ユーザーが直接⽬にしないもの であることが多い
ユーザーが直接に⽬にするものついては…
やったこと
まずはTypeScriptをコンパイルできるように ・既存のjsファイルのビルド結果を変えないように ・JavaScript → TypeScript に変換したものや 新規で書いた TypeScript のコードだけが正しくトランスパイルできればOK ・ビルド時間の増加について⼀旦スルー
・Vueのファイルについても⼀旦考えない 以下の⽅針でまずははじめてみる
まずはTypeScriptをコンパイルできるように 1. TypeScriptのビルド環境を整えつつ、1つだけ⼩さめのファイルをTS化した ・ビルド⽣成物を⾒て、そのファイル以外の差分がないことを確認した 2. tsconfig の allowJS オプションを有効にした ・TS→JSの参照の場合、jsDocがちゃんと書かれていれば
型チェックをしてくれる /** * @param {Number} id */ export function getArticle(id) { // 略 } import { getArticle } from 'foo' export function doSomething(id: string) { const article = getArticle(id) } foo.js bar.ts
まずはTypeScriptをコンパイルできるように 3. tsconfig の target を es2019 にした → ts-loader→babel-loaderを通すときに、tsでトランスパイルをしてほしくなかった
→ spread-arrays や rest-spread は、今まで通りbabelでpolyfillを⼊れてほしい → tsのトランスパイルで差し込まれるpolyfillで挙動が変わるかもしれない みたいな⼼配をしたくなかった // spread-arrays const nums = [ 1, 2 ]; const newNums = [ 0, ...nums ]; console.log(newNums); // [ 0, 1, 2 ]; // rest-spread let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 }; console.log(z); // { a: 3, b: 4 }
VueのSFCファイルをTS対応にする ・Vueの型定義を追加 ・まずはVue.extendを使う形に書き換えてみた(1ファイルだけ) → 差分が出るので、ここは⾃分で動作確認。問題ないことを確認 declare module '*.vue' { import
Vue from 'vue'; export default Vue; } export default Vue.extend({ props: { propA: { type: Number } } }) export default { props: { propA: { type: Number } } }
VueのSFCファイルをTS対応にする import { Vue, Component, Prop } from 'vue-property-decorator' @Component
export default class FooComponent extends Vue { @Prop(Number) readonly propA: number | undefined } export default { props: { propA: { type: Number } } } "vue-class-decorator" や "vue-class-component" があるが、導⼊を⾒送った ・書き換え量が多いこと ・Vue3のRFCではrejectされていること → これは特に⻑く続いているプロジェクトとして気にした また⼤規模に書き換える必要がありそうなら、ここでやることはないと判断 Example: vue-class-component
ビルド時間の短縮 TypeScriptを導⼊してから、ビルドに倍以上の時間がかかるように "fork-ts-checker-webpack-plugin" を導⼊して、型チェックのプロセスを分離した Before / 117s After / 41s
ts-loader fork-ts... ts-loader ts js ts js type-check & transpile type-check transpile
ビルド環境のシンプル化 ts-loaderでJavaScript / TypeScript 両⽅ビルドするようにした → 数秒ビルド時間が伸びる程度・環境のシンプルさを優先 module.exports = {
module: { rules: [ { test: /\.js$/, use: babelLoader, }, { test: /\.ts$/, loader: [ babelLoader, tsLoader ], } ] } } module.exports = { module: { rules: [ { test: /\.(js|ts)x?$/, loader: [ babelLoader, tsLoader ], } ] } } Before / 41s After / 45s
テストの導⼊ QAをしてもらえるとはいえ、しょうもないエラーを出すのは申し訳ない ⼀定のクオリティーを担保するためにテストを導⼊した ・KarmaからJestに移⾏した ・windowオブジェクトを使うテストが書きやすい → location.href を変更するようなコードとか ・jest.resetModules() が便利だった
→ コード中の変数でキャッシュしているコードなど ・新しく書くコード(特にユーテリティ系とか)を中⼼にテストを追加した
知⾒やハマり
リファクタ / コード修正したい気持ちはグッとこらえる 書き換える時点で「このコードおかしくない?」とか「改善できそう!!」 など、気づく点がいっぱいあると思う ⼀緒に着⼿してしまうと ・レビューのコストが上がる ・ts化とコード改善を⼀緒になると、問題が起きたときの切り分けしづらくなる みたいな問題があるので、⼼を⻤にしてコード⾃体の改善はしないようにした コード中にコメントを埋め込んだり、PRにメモを残すようにして
別のコミットやPRとしてコードの改善は⾏った
TODO<T>: any で "攻めながらanyを使う" js → ts に拡張⼦を変えただけでビルドが通らなくなるケースはあるはず そんなときにTODO型を使うと ・とりあえずビルドを通すことができる
・やるべき型をメモしておけるので、anyより便利 // 内部的にはany でエラーを回避しつつ、本来当てたい型をメモしておける const foo: TODO<Article> = getArticles(); const foo = getArticles(); // なんかエラー出るんだけど!!! ↓
Vueの型解決エラーはComputedの返り値を書け ・VueのSFCをTS化する最中に、どうしても this.hogehoge の型が解決できないときがある ・こういうときはcomputedの返り値を明⽰的に書くことでほとんど解決した computed: { getOpacity(): number {
return this.isActive ? 1 : 0; } } 注釈: 循環参照の都合上こうなってしまうようです。詳しくは公式ドキュメント参照 → https://jp.vuejs.org/v2/guide/typescript.html#戻り値の型にアノテーションをつける
まとめ
まとめ ・TypeScriptは段階的に導⼊することができる ・いきなり全部TSに書き換える必要はない ・可能なら⼀緒にユニットテストも書くとより安⼼かも ・プロジェクトに⼊ったばかりだからこそ、⾔える/思うようなこともある ・⾃分が困ったことは、今後新しくプロジェクトに⼊るメンバーも困るはず ・昔の技術を勉強するより、持っている最新の技術スタックで 即戦⼒になれるほうが双⽅ハッピーなはず
お知らせ LINEやLINE Growth Technologyで働くことに興味のある⽅向けに 社員と直接情報交換ができるカジュアル⾯談を実施しています 興味のある⽅は、「LINE Developer meetup」で検索をお願いします!
ありがとうございました!