こんにちは。kintone開発チーム Webエンジニアの村田 (@mys_x101) です。
本記事では kintoneのフロントエンドの刷新をはじめるに至った経緯と、その取り組みについて紹介します。
はじめに
現在 kintone 開発チームでは、フロントエンドの開発に使用している Closure Tools (Closure Compiler、Closure Library、Closure Templates で構成されるツール) を React をはじめとした技術スタックに移行する取り組みを進めています。
kintone のフロントエンドは10年以上前から Closure Tools を用いた開発を続けており、JavaScript だけでも50万行を超えるソースコードで構成されています。これらを昨今のモダンフロントエンドの技術に置き換えることは一朝一夕にできるものではなく、ビジネスへの影響を最小限にしながら少しずつ移行を進めていく必要があります。kintone 開発チームでは2年前からフロントエンドの負債と向き合い、段階的に技術の刷新を進めています。
なぜフロントエンドを刷新するのか
kintone はサービス開発当初から Closure Tools を用いて開発を続けています。古くからある重厚なフレームワークであり独自のエコシステムを持っているため、現代のフロントエンドエコシステムで確立されたプラクティスを利用できず、ツールのメンテナンスに開発リソースを確保し続けています。
また、Closure Tools は開発元である Google の外で広く使われている技術ではなく、Closure Tools を用いた開発を継続することは、開発人員を増やして組織をスケールさせることを困難にしています。
Google 内でも Closure Compiler をやめて TypeScript に移行する動きがあり、プロジェクトの継続性に対するリスクもあります
これらの問題は、今後 kintone の開発を加速させ、ユーザーに届ける価値を最大化するための大きな障壁になります。世界中の人に利用されるプロダクトにするためには、Closure Tools との決別を果たし、新しい技術スタックで kintone のフロントエンド開発をより加速させる必要があると判断しました。
小さくはじめる
今動いているコードを捨てて新しいコードに書き換える行為は新たなバグを発生させる原因になります。レガシーコードを改善するためのリファクタリングで新たなバグを生み出してしまっては元も子もありません。
では、安全にリファクタリングしていくにはどうすればよいのでしょうか?
1つは小さくすることです。
特に大規模なリファクタリングを行うときは、スコープを小さくして戦略的撤退の余地を残しながら進めていくことが定石です。
kintone 開発チームの場合は、2019年の中頃から有志のメンバーで週1~2時間ほど時間を確保して PoC(Proof of Concept)を実施するところから始めました。
Proof of Concept
PoC では主に以下の観点で検証を行いました。
・ 既存の技術で実現できていることが移行後の技術スタックで実現できるのか? ・ 新規機能の開発と並行して技術の移行を行う仕組みを作れるのか? ・ 既存資産をどこまで使い回すことができるのか?
取り組んだことは React と Closure Library の共存、React から Closure Library のコンポーネントの利用、Closure Library のコードを AST ベースで自動で TypeScript に変換、などがあります。
以下のブログで紹介した内容も最終的には採用しませんでしたが PoC の成果物の1つです。
このように、最初は目標も人数も時間も小さくして検証をするところから始めました。
リリース戦略を考える
PoC で刷新の見通しが立ってからは、プロダクトマネージャーと相談して一緒にリリース戦略を考えました。
最初に置き換える画面は以下の観点で選定しました。
・ 技術の刷新によるユーザーへの悪影響が小さい = サードパーティ製品への影響が小さく、不具合があっても自社で解決できる。 ・ ユーザーに付加価値を提供できる = 技術の刷新の恩恵をユーザーが享受できる ・ 開発者にとって価値が高い = 今後も機能追加や修正が行われる
技術の刷新によるユーザーへの影響で、最も懸念があったのはkintoneカスタマイズへの影響です。
kintone にはユーザーが JavaScript で振る舞いや見た目をカスタマイズできる機能があります。kintone で発生するイベントをトリガーにして、ユーザーが任意の JavaScript を実行したり、API 経由で情報の取得や設定ができます。*1
この仕組みを使って kintone を拡張し、プラグインとして提供している企業も多数存在します。
ここで問題なのは、ユーザーが作成したカスタマイズの中には、kintone の DOM の構造や CSS のクラス名に依存しているものが存在するということです。kintone の DOM に依存したカスタマイズは、移行によって DOM の構造が変更された場合に正常に動作しなくなる可能性があります。
kintone の DOM, CSS に依存したカスタマイズはサポートの対象外ではありますが、ユーザーへの影響を考えると、現状の仕組みのままフロントエンドの実装を大きく変更することは難しいです。一方で、ユーザーへの悪影響を気にしすぎるあまり、ユーザーがほとんど利用しない画面や、今後追加機能や修正が発生しないような画面を選ぶと、刷新するメリットがほとんどなくなってしまいます。
これらのことを考慮すると、まずは kintone カスタマイズが適用されない範囲に絞り、その上でユーザーと開発者双方に価値がある画面から刷新するという結論になりました。
※kintone カスタマイズが適用される画面の刷新については別途検討中です。
移行前と移行後の技術スタック
PoCの結果から適当な技術を選びました。*2
移行前 | 移行後 |
---|---|
JavaScript | TypeScript |
Closure Tools | React, Redux Toolkit |
Sass | styled-components |
Mocha | Jest |
技術選定の理由は説明すると長くなるので、また別の機会にご紹介させていただければと思います。
既存資産の再利用
フロントエンドに関わるすべての技術スタックを刷新するのは大変なので、一部の資産は再利用することを検討しました。
検討した内容をいくつかご紹介します。
Closure Library製の複雑なコンポーネントを再利用する
どうしても移行が難しい、または開発に時間のかかるコンポーネントは、既存の Closure Library 製コンポーネントを再利用することを考えています。
Closrue Library をグローバルオブジェクト経由で React 側から参照すれば、Closure Library で作られた既存のコンポーネントを利用できます。具体的には、goog.exportSymbol, goog.exportPropertyで、使いたいネームスペースを指定し、Closure Compiler が圧縮後も参照できるようにすると実現できます。React から呼び出したい Closure Library のコンポーネントがグローバルに露出するため、使用するときはその影響を確認する必要があります。
Closure Library で作成したコンポーネントを React でラップしたものを npm module として公開し、React のプロジェクトで読み込むという方法も考えられます。ただし、Closure Library ↔ React 間で Closure Library のイベントが扱えるかはケースバイケースであり、すべてのコンポーネントを React でラップして使えるわけではありません。そもそも Closure Library の実装に頼りすぎると本末転倒なので、どうしても移行が難しい場合に最後の手段として利用します。
E2Eテストを再利用する
kintone は E2E テストに Selenium を使用しています。
この機会に別のテストツールに移行することも検討しましたが、結論としては Selenium の使用を続ける選択をしました。別のテストツールに移行する場合は、DB を初期化したりユーザーを作成したりなどの UI を操作する前段階の処理も再度実装する必要があり、それらの再実装コストに見合うメリットがありませんでした。
スタイルを再利用しない
Scss で書かれた既存のスタイルを捨て、一から styled-components で書き直していく決断をしました。
既存の Scss が@mixinや@extendを多用していて、かなり複雑な状態になっていたこと、それが課題として認識されてたのが大きな要因です。課題を解決するより、新しく書き直した方がコストが低いと判断しました。
styled-components の採用を決定するまでの過程や、既存の Scss ファイルの扱いについては「styled-componentsの採用と既存資産を捨てた理由」に詳しい内容が記載されておりますのでそちらをご覧ください。
開発体制
現在 kintone 開発チームメンバー5名でフロントエンドの刷新に取り組んでいます。2020年4月から開発リソースを確保して、プロダクトマネージャーと相談しながら新規機能開発と並行して刷新を進めています。
各支援系チームのおかげで、開発チームはアプリケーションのドメインに集中できる体制になっています。
フロントエンドエキスパートチームの支援
フロントエンドの設計、技術選定、一部の複雑なコンポーネントの探求など、フロントエンドに関わる様々なことをフロントエンドエキスパートチームと相談しながら開発をしています。定期的に kintone のフロントエンドの今後について話し合い、先回りで技術的な検証も実施していただいています。
アクセシビリティチームの支援
既存画面や既存コンポーネントが提供していたアクセシビリティより良い品質のものをユーザーに届けるために、アクセシビリティチームと協力しながら開発をしています。
元々 Closure Library が担保していたアクセシビリティ対応は別途担保する必要があり、暗黙的に対応されていたものは、その調査から必要になります。完全再現が React/TypeScript の流儀的に微妙かつ、実装にかかるコストを考えるとどの辺りを落とし所にするかの判断が難しいため、適宜相談させていただいています。
生産性向上チームの支援
生産性向上チームには、開発チームの業務の自動化や効率化の支援をしていただいています。
今回の開発では CI/CD 周りや Storybook のホスティングの整備をしていただきました。
Storybook のホスティングについては「プロダクト支援チームでkintoneのStorybookをホスティングした話」に記載されておりますのでぜひそちらをご覧ください
これからの活動
kintone 開発チームとしては、既存の技術を使い続けることによる問題を早急に改善したいと考えているため、今後より一層リソースを投入して刷新を進めていく方針です。
多数のユーザーを抱えながらの改善は難易度の高い挑戦になりますが、エンジニアとしての真価を発揮するチャンスでもあります。私たちは kintone のフロントエンドを再構築し、一緒に開発を加速させる基盤を作っていく気概のある方々のご参加をお待ちしております!
おわりに
kintone のフロントエンドの刷新をはじめるに至った経緯と、その取り組みについて紹介しました。
サイボウズでは世界で通用するプロダクトを目指して、今後さらに力を入れて kintone のフロントエンドの刷新を進めていきます。今回紹介した取り組みを一緒に進めてくれる頼もしい仲間を募集しておりますので、ご興味のある方はぜひご連絡ください!
*2:2020年4月に技術選定を行いました。