9年ほど運用しているjQueryで実装された「楽楽明細」というサービスをTypeScriptに移行した事例を紹介します。
#RAKUSTechCon©2022 RAKUS Co., Ltd.©2022 RAKUS Co., Ltd.トラブルゼロで乗り切ったTypeScript移行株式会社ラクス 開発本部 第3開発部 楽楽明細開発課Eiichi Mita2022/2/8 RAKUS Tech Conference2022
View Slide
#RAKUSTechCon©2022 RAKUS Co., Ltd.自己紹介Eiichi Mita @eichisanden■経歴ソフトハウス、独立系Sierを経て2014年ラクスに入社。以来、楽楽明細の開発・運用を担当テックリードとしてフロントエンドからバックエンドまで継続的な改善や、スクラムマスターとしてチームビルディングに取り組んでいる趣味はスプラトゥーン2(Sからウデマエが上がらないのが悩み)
#RAKUSTechCon©2022 RAKUS Co., Ltd.今日お話しすること9年ほど運用しているjQueryで実装された「楽楽明細」というサービスをTypeScriptに移行した事例を紹介します。
#RAKUSTechCon©2022 RAKUS Co., Ltd.今回お話するプロダクト「楽楽明細」• 請求書などの帳票を発行するSaaS• ローンチから9年ほど経過しているが成長しているサービス
#RAKUSTechCon©2022 RAKUS Co., Ltd.今年姉妹サービスの「楽楽電子保存」をリリースしました• こちらもTypeScriptで実装しています
#RAKUSTechCon©2022 RAKUS Co., Ltd.目次• はじめに• どう移行を進めたか• うまくいった施策• 移行して良かったこと/苦労したこと• さいごに
#RAKUSTechCon©2022 RAKUS Co., Ltd.• はじめに• どう移行を進めたか• うまくいった施策• 移行して良かったこと/苦労したこと• さいごに
#RAKUSTechCon©2022 RAKUS Co., Ltd.移行前の状況と前提事項• リリースは数か月サイクル• 開発メンバーの中に実務でのTypeScript経験者はいない• 古くからの機能はjQuery、新しい機能はReactで実装されている• JavaScriptファイル数は100程度の規模• 作業に関わるのは自分と若手2名(週数時間ずつ)• 開発を止めずに移行する必要がある• npmでのパッケージ管理やgulpでのビルドは以前から行っていた• IEなど古いブラウザもサポートする必要がある
#RAKUSTechCon©2022 RAKUS Co., Ltd.TypeScriptとは• Microsoftが開発しているプログラミング言語• 静的型付け言語• JavaScriptにトランスパイルして実行するAltJSの一種• TypeScriptを直接実行するのではない• AltJSは色々あったが現在はTypeScriptを選んでおけば良い状況
#RAKUSTechCon©2022 RAKUS Co., Ltd.なぜTypeScriptに移行するのか?/ 良いところ• Reactを導入したことでフロントエンドで型が重要に• jQueryはDOM操作が中心で、複雑なデータ構造を扱うケースが少なく、型はそこまで重要ではなかった• Reactではstateやpropsなどでデータ構造を扱うため、型がないと安全にプログラミングすることが難しいと感じた
#RAKUSTechCon©2022 RAKUS Co., Ltd.なぜTypeScriptに移行するのか?/ 良いところ• 導入ハードルの低さ• 既存のJavaScriptのコード=TypeScriptでも有効なコードである• 従って部分的に移行することも可能• 最悪の場合は戻すことも可能
#RAKUSTechCon©2022 RAKUS Co., Ltd.なぜTypeScriptに移行するのか?/ 良いところ• 実装・トランスパイル時にエラーを早期検知できる• 基本的にはJavaScriptは実行してみないとエラーが分からない• 現状、フロント側のエラーを検知する仕組みは作れていないため開発時に発見したい
#RAKUSTechCon©2022 RAKUS Co., Ltd.なぜTypeScriptに移行するのか?/ 良いところ• モダンな構文が使える• IEなどレガシーなブラウザに対応する場合でも、トランスパイルするのでモダンな構文を使って開発できる※TypeScriptでないと出来ない訳ではありません
#RAKUSTechCon©2022 RAKUS Co., Ltd.どう移行を進めたか1. 事前準備フェーズ2. 移行フェーズ
#RAKUSTechCon©2022 RAKUS Co., Ltd.事前準備フェーズ「プログラミングTypeScript」読書会を実施• 少し難しいがこの1冊で大体分かる良書• 有志で全10回開催• 全社的に声を掛けたので20名が参加• TypeScriptの人気がうかがえる• 会社に20冊買ってもらいました• ほぼ素人だったが無理やり講師に• 講師駆動学習• 参加できないメンバーにはポイントに絞った勉強会を別途開催
#RAKUSTechCon©2022 RAKUS Co., Ltd.移行フェーズDefinitely Typed(ライブラリの型情報)をインストールする$ npm install -D @types/jquery @types/jqueryui @types/react @types/react-dom @types/react-router-dom• 移行時は手動でインストールしましたがtypesyncで一括にインストールすることも可能$ typesync├─ + @types/react-datepicker├─ + @types/react-redux├─ + @types/react-router├─ + @types/react-select├─ + @types/react├─ + @types/react-dom└─ + @types/styled-components• Jsで公開されているライブラリの型情報がないとTypeScriptがエラーになるため必要• GitHubのDefinitely Typedに型情報が公開されているものは有り難く使わせていただく
#RAKUSTechCon©2022 RAKUS Co., Ltd.移行フェーズDefinitely Typedで公開されていないものは自作するinterface JQuery {// jquery.datePicker.jsdatePicker(options: any);// jquery.ajaxfileupload.jsajaxfileupload(options: any);}• jQueryプラグインなど古いライブラリは公開されていないものがある• それほど多くなかったので使用しているメソッドに絞って自作しました• 今後呼び出し箇所を増やすことはないので頑張らずanyを使用しました
#RAKUSTechCon©2022 RAKUS Co., Ltd.移行フェーズts-migrateを使って機械的にTypeScript化• Airbnbが提供している移行ツール• 実行すると下記の流れで移行される• tsconfig.json生成• 拡張子js/jsxファイルをts/tsx にリネーム• ts/tsx ファイルを一括変換https://medium.com/airbnb-engineering/ts-migrate-a-tool-for-migrating-to-typescript-at-scale-cd23bfeb5cc
#RAKUSTechCon©2022 RAKUS Co., Ltd.移行フェーズts-migrateを使って機械的にTypeScript化• 1ステップずつ結果を確認しながら実行するのがお勧めd2e91aeb77e04ec5cb449b5687b4d435f74f4975 (HEAD -> master) [ts-migrate][src] Run TS Migrate5dbe3669ec05232824dcb42c321d18983e451a54 [ts-migrate][src] Rename files from JS/JSX to TS/TSXbae0dfb6790808310865ceb7f00ab0c0f161013a [ts-migrate][src] Init tsconfig.json file• コミットも段階的にしてくれるので結果を確認しやすいnpm run ts-migrate -- init Initialize tsconfig.json file in npm run ts-migrate -- rename *Rename files in folder from JS/JSX to TS/TSXnpm run ts-migrate -- migrate *Fix TypeScript errors, using codemodsnpm run ts-migrate -- reignore Re-run ts-ignore on a project
#RAKUSTechCon©2022 RAKUS Co., Ltd.移行フェーズwebpackを導入• TypeScriptのトランスパイルを行うためwebpackを導入• 今までと同じ単位でjsファイルを出力するためentryを複数定義するentry: {‘huge/huga.js’: ‘src/hoge/huga.ts’,‘foo/bar.js’: ‘src/foo/bar.ts’…},…output: {libraryTarget: ‘umd’,filename: ‘[name]’}module: {rules: [{test: /¥.(ts|tsx)$/,exclude: /node_modules/,use: {loader: 'ts-loader',options: {transpileOnly: true,}}},]}
#RAKUSTechCon©2022 RAKUS Co., Ltd.移行フェーズ@ts-expect-errorをひたすら修正していく• 修正すべきことをts-migrateが@ts-expect-errorで教えてくれているので、そこをひたすら修正するtype="text"ref={refY}defaultValue=""// @ts-expect-error ts-migrate(2322) FIXME: Type 'string' is not assignable to type 'number | ... Remove this comment tosee the full error messagemaxLength="4"className="text_alphanumeric input_year"onBlur={handleInputY}/>
#RAKUSTechCon©2022 RAKUS Co., Ltd.うまくいった施策TypeScript移行以外を同時にやらない• ついでに直したくなることが沢山でてくるが我慢する• トラブルが出たときに切り分けが難しくなるのを避ける
#RAKUSTechCon©2022 RAKUS Co., Ltd.うまくいった施策Diffで比較する• 両者を比較して一致すれば動作確認せずとも問題ないと判断できる• 移行前のJavaScript• 移行後のTypeScriptをトランスパイルしたJavaScript
#RAKUSTechCon©2022 RAKUS Co., Ltd.移行して良かったこと次のサービス開発に活かせた• 経験があるのでスムーズにTypeScript導入できた• 開発期間も短かかったのでいきなり導入は厳しかった
#RAKUSTechCon©2022 RAKUS Co., Ltd.苦労したこと圧倒的なTypeScript力不足• 事前に勉強会して知識を得ていたが難しかった• ts- expected- errorをどう消せば良いのか分からない• 一つずつ調べながら地道に潰すしかない• どうしても難しいものは後回しにしても問題ない
#RAKUSTechCon©2022 RAKUS Co., Ltd.苦労したこと話しきれないことは以前に記事を書いているので参照ください• 既存のMPAなシステムをTypeScriptに移行した時のメモhttps://qiita.com/EichiSanden/items/7ebe085904d1c32ae90e
#RAKUSTechCon©2022 RAKUS Co., Ltd.さいごに• トラブルを発生させず移行を乗り切ることができた• 無理しないことが重要• 新しいサービスも繋げることが出来るので、レガシーシステムの技術刷新は重要
#RAKUSTechCon©2022 RAKUS Co., Ltd.ご清聴ありがとうございました