Re:Tepa を Vue から React に書き換えた
Re:Tepa は、元々 TepaEditor という名前で公開していたテキストエディターのリメイク版という位置づけのアプリ。
TepaEditor は Delphi製の Windowsネイティブアプリだったが、Re:Tepa は Webアプリを Electron によってネイティブアプリ化している。
Re:Tepa の最初のバージョンである 0.1.0 では Webアプリのフレームワークとして Vue2 を採用していたが、今回 2年半ぶりにリリースした 0.1.1 では React に変更した。
それに伴い関連するライブラリーや開発ツールなども全面的に置き換えとなった。
主な変更内容がこちら。
- Webフレームワーク:Vue (vue-cli) → React (Create React App)
- ルーティング:vue-router → React Router
- ステート管理:Vuex → Recoil (+Recoil Nexus)
- i18n:vue-i18n → react-i18next
- CSSトランジション、アニメーション:Vue → React Transition Group
- CSS:Vue(sass) → styled-components
- 画面分割:vue-resize-split-pane → Allotment
- Electron ビルド:electron-builder (vue-cli-plugin-electron-builder) → Electron Forge
- e2eテスト:Spectron → Playwright
以下は元のままで最新版に更新。
- ネイティブアプリ化:Electron
- エディターエンジン:Monaco Editor
- ユニットテスト:Jest
- リンター:eslint
- コード整形:Prettier
基本的には Vue で使っていたライブラリーを React で実現するためのライブラリーに置き換えている。CSS、アニメーション周りは Vue 自体の機能 (+WebPack) として提供されていたが、React については相当するものがないので外部のライブラリーを新たに追加した。
ステート管理には Facebook が開発している Recoil を採用。まだベータ段階だが、扱いが Redux や元の Vuex と比べても非常に楽なので使ってみたいと思い、先行して採用することにした。
ちなみに Recoil は基本 hooks のインターフェイスしか持っていないため、React コンポーネント外からの値の更新ができない。そこで Recoil Nexus というライブラリーを使って、React の外側からでも更新ができるようにした。Recoil Nexus は中身的には Recoil の useRecoilCallback で提供される get, set メソッドを無理やり外に出して (一旦空コンポーネントから hook を呼び出して内部で保持している) 参照できるようにしているもので、ちょっと裏技感があるなと思いつつ、今のところは問題なく動作しているので様子を見つつ使っている。
e2e テストやビルドツールの変更については別の機会に。
そしてこちらが Re:Tepa の構成図。(ちょっと小さくて見づらいが...)
基本的には React の部分が Vue から置き換わったのだが、それ以外の部分もごちゃごちゃして役割分担が曖昧になっていたので、Reactへの書き換えに合わせて整理して React → Commands → Searvices(Operators) → Recoil → React という流れの完全な単方向データフローになるように修正した。(むしろそっちの方が時間がかかった。) ただ、Monaco Editor がちょっと他の Reactコンポーネントからは独立した位置づけにあるので、若干矢印がややこしくなっている。
Service の中に Operator というのがあるのが若干冗長に見えるかかもしれないが、ちゃんと理由がある...のだが、この点についてもまた別の機会に。
Action というのは、元々は Delphi のライブライリー(VCL)にあった TAction というクラスを模したもの。1つのアクションを複数のコンポーネントに紐づけることで、共通のステートやメソッドを扱えるという便利なもので、Vue の時はプラグインの形で実現していた。React の場合は hooks とステートで同じような事ができてしまうので、カスタムフックと Recoil を組み合わせて Action に近いことを実現している。
書き換えの理由
Vue から React に乗り換えた最大の理由はモチベーション。
元々は Vue 最高! React イヤだ! JSX キモチワルイ!くらいの Vue派だったのですが、業務で本格的に React を触るようになって React 意外と悪くない!hooks 便利!JSX はやっぱちょっと...くらいに思うようになっていった。
加えてなかなかリリースされない Vue 3 (ようやくされたけど) 、そしてそこで採用予定の Composition API の直感的ではない点に嫌気が差し、Vue と React の立場が完全に逆転。
そしてしばらく放置状態になってしまった Re:Tepa を Vue で書かれたままにしておいたら、いよいよもってこのまま触らなくなってしまうと危機感を感じだし、最初のリリースから 1年経った 2021年末ごろから書き直しに着手することにした。
その後も仕事とゲームのの合間を縫ってちょこちょこ書き直していき、ようやく元の状態にまで持ってくることができた。
まあ React もあとどのくらい持つのか、という話もあるが、少なくとも突然消えて他に移り変わることはない...かもしれない...(し、そうなったら何で書いてても一緒)ので、とりあえずはこれを機にペースアップしてければと思う次第である。
また、開発の中でいろいろと得られた知見も多いので、それらも徐々にまとめで出せていければと考えている。
以上、よろしくお願いいたします。