レガシーシステムの大規模リプレイスで分かった「Vue.jsでSPAならNuxt.jsが有力」

10年以上前に作られたレガシーシステムをVue.jsで大規模リプレイスしたエムスリーに、導入して感じたVue.jsのメリットや、活用法を伺いました。

レガシーシステムの大規模リプレイスで分かった「Vue.jsでSPAならNuxt.jsが有力」

JavaScript(JS)のフレームワークは、何を使うのがベストなのでしょうか。ここ3年ほどで数々のJSフレームワークが誕生していますが、React、Angularという二大巨塔を超えるものはなかなか現れていません。

そんな状況の中、GitHubではReactを上回るスター数を誇っている1のが、2014年のリリース後、着実に進化を重ね、日本でも採用事例が増えてきているVue.jsです。「JavaScript ベスト・オブ・ザ・イヤー」に2016年、2017年と2年連続で選ばれているほか、Ruby on Rails(Rails)やLaravel といったサーバサイドのフレームワークが公式サポートを開始。11月には「Vue Fes Japan」という日本初のVue.jsカンファレンスが開催されます。

そこで今回は、10年以上前に作られたレガシーサービスの大規模リプレイスにVue.jsを採用した「エムスリー株式会社」にお話を伺いました。導入決定当時、チーム内にVue.jsの開発経験者がほとんどいなかったにもかかわらず、リプレイスの要としてVue.jsを選択したのはなぜなのか。ライブラリの活用方法や開発したからこそ分かったノウハウなどと合わせて紹介します。

前原秀徳(まえはら・ひでのり/@maeharin)(写真右)
2014年にエムスリーに入社。チームリーダーやグループ会社の取締役を歴任後、Vue.jsとサーバーサイドにKotlinを用いたシステムリニューアルプロジェクトを立ち上げ、リーダーとしてチームを牽引する。
鈴木健太(すずき・けんた/@suusan2go)(写真左)
2017年入社。入社以前はReactの開発経験があり、入社直後にレガシーシステムのリニューアルを経験。現在は社内の新規事業立ち上げにエンジニアとして関わっており、機械学習を活用したサービスのアーキテクチャ設計など、技術選定から携わる中心メンバーとして開発を行っている。

Vue.jsを選んだ3つの理由

――エムスリーさまではレガシーなシステムをVue.jsを用いて1年ほどかけてリプレイスされており、そろそろ完了が見えてきているころだと伺いました2。どのようなサービスをリプレイスしたのでしょうか?

前原:私たちは主に医療関係のサービスを提供しているのですが、その中でも今回は、医師のキャリア支援サービスと薬剤師のキャリア支援サービスの2つをリプレイスしました。フロントはVue.js、バックエンドはRailsとKotlinを使っています。事業規模は年間売上が約100億円。各システムのデータベースのテーブル数はそれぞれ150~200個くらいの規模感です。

―― 大規模なサービスですね。具体的に、どのようなリプレイスを行ったのでしょうか。

前原:私たちが手掛けているサービスには、一般ユーザーが求人情報を検索するための“表”側と、医療機関や企業が求人情報を管理する“裏”側があるのですが、今回は医師向けと薬剤師向けの2つのサービスで、“裏”側の管理画面改修を行いました。

ビジネスは10年で約10倍の売上規模に成長と大成功したのですが、パッチ的に機能追加を繰り返した結果、システムのレガシー化が進み、特に”裏”側の管理画面がまともに開発ができない状態になっていました。これを何とかしたいと思い、今回のリプレイスを行いました。2017年の5月から医師向けのサービス改修を始め、2017年の11月から、鈴木さんに薬剤師向けのサービス改修を始めてもらいました。

1

―― リプレイスで特に苦労した点があれば教えてください。

前原:10年ほど前の古い技術スタックが使用された、かなりのレガシーシステムで、バックエンドからフロントエンドまでリプレイスが必要でした。バックエンドはJavaの独自フレームワークを使っていて、ドキュメントもない。「ググっても分からない」というのはかなりつらかったですね(笑)。また、単体テストがないので、動作確認がつらい。バグを生んでも気付きづらいため、追加改修がほとんど行えていない状態でした。

フロントはテンプレートにXSL Transformations(XSLT)を使用し、動的な部分はjQueryで制御していました。管理画面は機能が多くUIが動的に変化する箇所も多かったのですが、jQueryでゴリゴリに組んでいる部分はさまざまな箇所にデータがバインディングされていて、誰も触れないような状態になっていました。

鈴木:バックエンドでやるべき処理をフロント側で無理やり行っている部分もあって、XSLTにいろんなロジックが漏れていたので、ソースコードを読むだけでもつらかったですね(笑)

前原:なので今回のリニューアルではバックエンドからフロントエンドまでまるっとリプレイスしました。APIサーバはKotlinを使用し、それをRailsがプロキシのような形で叩いて、フロントはVue.jsに任せるという構成です。鈴木が担当した薬剤師向けのサービスはNuxt.jsを使用しているので、よりシンプルな構成になっています。私が医師向けサービスを改修し始めたときは、Nuxt.jsがまだベータ版だったので使用していませんが、今からやるのであれば絶対に使っていますね。

Nuxt.js:ユニバーサルなVue.jsアプリケーションを構築するためのフレームワーク。サーバサイドレンダリングが実装できるだけでなく、Vue RouterやVuex、webpackなどが標準で用意されている。

―― Vue.jsの開発経験者はチーム内にいたのでしょうか?

前原:チーム内はもちろん、全社的にもほぼいませんでした。そのため、リニューアルプロジェクトで導入する前に、他の小さめのプロジェクトで本番導入してチームメンバーに触れてもらったり、リニューアルのためのプロトタイプをVue.jsで実装してみるという方法からスタートしました。

―― 開発経験者がほぼいない状況の中で、なぜVue.jsを選んだのでしょうか?

前原:理由は大きく分けて3つあります。1つ目は触ってみたときに「分かりやすい」と感じたからです。日本語のドキュメントが多く、単一ファイルコンポーネントでHTML、CSS、JSが一つのファイルとしてまとめて管理できるのが良いと思いました。

2つ目は公式のライブラリが充実しているところです。Fluxアーキテクチャを使うときにはVuexが使用できますし、ルーティングもVue Routerが用意されています。ライブラリの選定に迷わないというのは、フレームワークにおいて大事な要素の一つだと思います。

3つ目はVue.js自体の採用例が多くなってきている点です。PHPのフレームワークであるLaravelもVue.jsをデフォルトで採用していますし、GitLabもVue.jsを使っていると発表しています。国内のコミュニティも活発化していますね。

Vuex:
Vue.js用の状態管理ライブラリ。アプリケーションの状態(state)を集中的に保持できるコンテナの役割を果たす。グローバル変数と違い、リアクティブに更新を行うことができる。

鈴木:また、フロントの経験がそこまでなくても始めやすいところがVue.jsの魅力の一つです。今回の開発は、エンジニアがサーバサイドもフロントエンドも行う形だったので、ちょうどマッチしたのだと思います。逆にフロントエンジニアのエキスパートがそろい、TypeScriptで型を守ってガチガチに進めるような開発であれば、ReactやAngularを採用した方がいい場合もあると思いますね。

2

また、Vue.jsは始めるときの学習コストはそれほど高くはないですが、さまざまな書き方ができる分、関わる人数が増えるとコードの足並みをそろえるのが大変になってくる面もあるので、状況によってフレームワークの選定は変わると思います。

―― Vue.jsはライブラリが充実しているとのことですが、何かおすすめのライブラリや、開発において必須なライブラリなどあれば教えてください。

前原:迷ったらまずは、Vuex、Vue Routerなどの公式でサポートされているライブラリを使用してみるのがいいと思います。あと、PC版の管理画面を作るのであればelement-uiはパーツが大量にそろっているためオススメです。私たちも今回のリプレイスで全面的にelement-uiを使っています。

鈴木:SPAを作るのか、一部分に適用するのかで使用するライブラリは変わりますが、SPAを作るのであればNuxt.jsは検討すべきだと思います。あと静的検証ツールのESLintprettierは、足並みをそろえてくれるのでおすすめです。

あとライブラリではないですが、Google Chromeの拡張機能である「Vue.js devtools」はとっても便利です。想定しない動きをした場合に、コンポーネントにデータが渡っていないのか、データが渡っているが表示がうまくできていないのかデバッグするのは大変ですが、Vue.js devtoolsを使うとコンポーネントが何を持っているのか、Vuexのストアにいまどんな値が入っているかが簡単に分かるんです。なので役に立つというよりは、むしろ「ないと開発がキツイ」くらいに活用していました。

レガシーシステムのリプレイスは「考古学」のよう

3

―― 鈴木さんは前職でReactを触っていたとのことですが、Vue.jsへの移行は苦労しませんでしたか?

鈴木:それほど苦労はありませんでしたね。むしろ、Reactで大変だったところが、Vue.jsだと楽に書けるということがあるくらいでした。例えばReduxでは、設計の際に「非同期処理をどこに書くべきか」が迷うポイントになりますが、Vue.jsはVuexのActionに書けるのでそこまで悩まなくて済みました。

ただユースケースが似ているとはいえ、Reactの設計をそのままVue.jsに持ってくるとつらいと思います。Reactではハイオーダーコンポーネントという、コンポーネントを別のコンポーネントでラップして、ロジックは上位のコンポーネントに持たせるという設計がよく知られています。しかしVue.jsで同じことをやろうとすると、propsの受け渡し方もReactとは異なりますし、Reactのようには型を付けられないので難しい。

―― やはり、それぞれに特徴や機能の違いはありますよね。ではVue.jsを採用した今回のリプレイスで、特に困った点は何でしょう。

前原:正直、Vue.jsというよりも仕様のリバースエンジニアリングが一番大変でした。動作確認するにもテストがないので、期待されるものが分からないという状況が多々ありました。 ER図を自動生成したり、DBの変更内容を検知するスクリプトを仕込んだりしながら、仕様を理解しつつ、昔のソースコードを読んで、ビジネスチームのメンバーに「これいるんですか?」とヒアリングして機能を整理して、コツコツ改修して……。どちらかというと開発よりコミュニケーションの方で時間がかかりました。レガシーシステムのつらいところですね。

鈴木:「こんな機能ありました!」というふうに新機能が発掘されることも多くて、まるで考古学みたいでしたね(笑)

―― まさに遺跡発掘ですね……(笑)

前原:Vue.jsに関してという観点だと、古いブラウザの対応をどうするかという問題はありました。移行前はIE8でも動作していたのですが、Vue.jsはIE9以上でしか動かないのでサポートを切る方針にしました。ただこれも、技術的な話というよりは、コミュニケーションの話かなと。

4

前原:あと、TypeScript関連は少し妥協が必要でした。Vue.jsはバージョン2.5でTypeScript対応が強化され、オブジェクト構文でもthisの型チェックが効くようになったのですが、今でもテンプレート部分の型チェックは効かないため、そこは諦めています。

鈴木:ReactだとJSXでJavaScriptをHTMLっぽく書けるので、そのあたり上手くやれるんですよね。Vue.jsでJSXを使用することもできますが、デファクトからは外れてしまうかなと思います。型のサポートはまだReactやAngularの方が上だと思います。

5

―― 改修を進める中で体得したVue.jsのバッドノウハウはありますか。

前原:バッドノウハウではないのですが、動的に変化するフォームを開発する際、APIの値をそのままv-modelでinput要素に双方向バインディングさせて、ポストするまで一つのオブジェクトでやろうとするとキツイ、ですかね。そういう場合は、APIから返ってくる値を他のオブジェクトにクローンし、ローカルな値で双方向バインディングして、ポストするときにオブジェクトへ詰め替えた方がいいと思います。

例えば「A」と選択した場合に次のページで10項目の選択肢があり、「B」と選択すると次のページで5項目になるようなフォームだと、フォームとデータのバインドが状況によって変わってきます。選択状態によって持つべき値が変わるとAPIサーバとオブジェクトの形が変わるので、今持っているデータがどんなものか分からなくなり、コントロールが効きづらくなるんですね。

フォームに対して最適化したローカルなオブジェクトを作り、APIに投げる方が楽です。もちろんケースによると思いますが。

鈴木:「watch」という変数の値の変更を検知して動作する非常に便利な機能が、意図せぬタイミングで発火するというケースもありました。

「watchした値だけど、状況によっては発火させたくない」というようにif文が複雑になる場合は、watchを使用するのはやめた方がいいと思います。例えば、ある値が変化したらフォームの一部をクリアするというwatchの処理がページ読み込み時に必ず発火してしまい、フォームの値が必ずクリアされて表示されるということが起こりました。

SPAを作るならVue.js+Nuxt.js

エンジニアHubに会員登録すると
続きをお読みいただけます(無料)。
登録のメリット
  • すべての過去記事を読める
  • 過去のウェビナー動画を
    視聴できる
  • 企業やエージェントから
    スカウトが届く