Vue.js向けvue-pivot-table-plus

坂口達彦氏(以下、坂口):ではこれから「Vue.js向けvue-pivot-table-plus」と題して、LINE株式会社の坂口が発表いたします。他のみなさんのセッションがフレームワークまわりの、ためになる話の中で、突然ピボットテーブルが出てきて「なんだそりゃ?」みたいな感じだと思います。ただ、少しマイナーな領域ではあるんですが、せっかくこのような機会をいただいたので、こんなものも作っているよという紹介のつもりでお話できればと思います。よろしくお願いします。

まず自己紹介をいたします。改めまして私はLINE株式会社の坂口達彦と申します。LINEのフロントエンド開発センター、UITのFront-end Dev8チームに所属しています。

次に私の簡単な略歴です。ちょうど私は2年前の冬、大学院在学時にLINEでインターンシップをしたことをきっかけに、アルバイトとして入り、そのまま2020年の4月に新卒として入社しました。現在2年目です。

ちょうどこの2年前のインターンシップで行った内容が、社内向けデータ分析ツールの改善という内容でした。この時のインターンレポートが弊社のEngineering Blogにて公開されています。画像は記事のスクリーンショットです。この時は本発表でも出てきます、OASISという社内向けデータ分析ツールのフロントエンドを改善していました。

フレームワークの最新版へのアップデートやデザインの改善もしていましたが、その中にピボットテーブル機能の追加がありました。今回のお話は、このインターンシップに加えて、アルバイトの頃にやっていたピボットテーブル機能に関する開発の話がメインになります。

それでは、本日の発表のアジェンダです。前半はメイントピックであるvue-pivot-table-plusの概要と、社内でどのように使われているかという導入事例についてお話しします。後半は開発の方向にフォーカスを当てて、このライブラリがどのように開発されたか、そして今後どのように改善していくかの方向性について話をしていきたいと思います。

Vue.jsとBootstrap環境向けのピボットテーブルコンポーネント

それでは、本発表の主役であるvue-pivot-table-plusについて紹介します。これは一言でまとめると、Vue.jsとBootstrap環境向けのピボットテーブルコンポーネントです。簡単に特徴をまとめますと、これは元々vue-pivot-tableというライブラリがありまして、それをForkして開発されました。

またこのライブラリの独自の点で言えば、パフォーマンスを改善したことと、カスタマイズ機能を導入したことなどが挙げられます。この辺りの詳しい話は後ほどします。また、このライブラリはオープンソースで公開がされています。

GitHubに加えて、npmでパッケージとして公開されていたり、またオープンソースとして公開する時にはLINE DevelopersのTwitterアカウントからも広報がされました。

ではもう少し詳しく、このライブラリについて見ていきたいと思います。その前にちょっと先にピボットテーブルについて軽くまとめます。こちらはExcelのスクリーンショットなんですが、左に表形式のデータがあります。ダミーデータなんですけど、左にあるdayという日ごとにpvやidというデータが保存されている状態だと考えてください。

これをピボットテーブルを用いて集計すると、右のような表になります。このスクリーンショットでは左の5月7日しか見えませんが、これが8、9、10とあると考えた時に、このピボットテーブルではそれを日ごとにpvを合算した数で出します。簡単に言うとこれがピボットテーブルです。

実際には、今はdayごとのpv加算しかやっていませんが、これに加えてdayとidのそれぞれのカテゴリごとに集計したり、あとは加算だけでなく平均、最大、ミニマムとか、さまざまな集計方法で行ったりできます。このように、表形式のデータを集計する強力なツールがピボットテーブルです。

それでは、このvue-pivot-table-plusを使ったサンプルの映像をお見せしたいと思います。まずはサンプルデータとして、画像のようなデータを使用します。country、year、gender、countというカラムがある表を、JSONで表現したオブジェクトになっています。このうち、一番右のcountを集計するカラムとして、残り3つを操作可能なフィールドとして使います。

まずは単純に、アプリを起動するとこのように、Available fieldsにCountry、Gender、Yearといったカラムが利用可能なフィールドとして格納されます。このフィールドはドラッグ&ドロップで移動できます。移動させると、そのフィールドの値ごとにcountの集計が行われます。こんな感じですね。

今はCountryを指定したので国ごとの集計がされていますが、さらにYearを列に追加することもできますし、Genderという行を増やすこともできます。また、必要なフィールドは自由にドラッグ&ドロップで動かせるし、一瞬出てきた左上の×ボタンみたいなものを押すと、リセットもできます。このように、さまざまな集計をGUIのみで直感的に行えるのが、このvue-pivot-table-plusというライブラリです。

vue-pivot-table-plusの特徴

次に、改めて本ライブラリの特徴を挙げていきたいと思います。まず、Vue.js+Bootstrap環境向けと謳っているだけあって、Bootstrapとの親和性が高い点が挙げられます。特に導入したプロジェクト側のBootstrapを利用しているので、テーマの設定をそのまま適用できます。社内のアプリケーションでも、このテーマを設定されたプロジェクトに導入して、プライマリのカラーなどをアプリケーションなどに合わせたりして、統一感を上げています。

次に社内での大量データに対応すべく、パフォーマンスを向上しています。社内では1万行あるデータを扱うことがあるんですが、そのようなデータでも処理が可能なように、パフォーマンスを向上しています。また、元のライブラリに加えて便利な機能をいくつか追加している点も特徴です。実際に、元のライブラリを導入してみて、使いづらかった点やこういう機能がほしいという要望があった点などを、追加機能として実装しています。

これについて例をお見せします。こちらがvue-pivot-table-plus独自の機能の例です。最初が左側のクリア機能で、フィールドの欄に出てくる左上の閉じるボタンを押すと、このカラムを一発でリセットできる、Available fieldsのほうに持って行ける機能です。次にデータの順序をソートできる機能です。特に時系列データの順序を最新順または古い順に並び変えるときに重要です。これは本当に強い要望があって導入されました。

また、ピボットしたデータをクリップボードやCSVにエクスポートする機能も搭載しています。PowerPointの資料を書く際や、またはPythonなどの別アプリケーションで解析するときなどにも使えます。

もう1つの特徴がデザインの調整です。マイプロダクトに合わせた変更ではあるのですが、左側のFork元であるvue-pivot-tableと比較して、右側のvue-pivot-table-plusは特にボタンサイズや余白を全体的にひと回り小さくして、スタイリッシュにまとめています。以上がvue-pivot-table-plusの特徴でした。

このライブラリはVue.js v2系とBootstrapのv4系に対応しています。発表の最後にも触れますが、両者ともv3とBootstrap v5が出ているので、ぜひ対応したいと考えています。

vue-pivot-table-plusの使用事例

では次に、このライブラリが社内でどのように使われているかについてお話しします。このライブラリはもともとLINE社内のデータ分析ツールでピボットテーブルを導入するために開発されました。そのため、社内の代表的なデータ分析ツールであるOASISとyanagishimaに導入されています。この2つのツールを紹介します。

まずはOASISです。OASISは、一言で言えば社内版Tableauみたいなもので、データのレポートを作成できるツールになっています。パラグラフと呼ばれるセクションごとに、SQLを書いて、グラフやテーブル、ピボットテーブルを用いてデータを可視化できます。

次がyanagishimaです。yanagishimaはPresto Web UIツールというもので、手軽にSQLを書いてデータを取得および確認できます。またグラフの描画機能やピボットテーブル機能も搭載していて、データの可視化もできます。

これはピボットテーブル導入前の話なんですが、これらのデータ分析ツールはエンジニアだけではなくビジネスの企画の方など、SQLに詳しくない方も利用します。SQLを用いてピボットテーブルと同様の集計もできるんですが、SQLに詳しくない方がそれを行うことは簡単ではなく、インタビューした際には一度データをダウンロードしてExcelに取り込んで集計することもあったという話を聞いています。

似たツールであるTableauにピボットテーブル機能が搭載されていたこともあって、これらの社内のデータ分析ツールにもピボットテーブルを導入できないかということでvue-pivot-table-plusの開発と導入が行われました。具体的な開発については、後半の開発セクションで詳しくお話しします。

開発の結果、これらを導入したことによって、データ取得のクエリを書くだけでGUIでのデータ集計が可能になりました。またダウンロードする必要もなく、Web上ですべての分析が完結することから、便利になったという話も聞きました。結果として、業務の効率化につなげられたと考えています。

あとは導入後もさまざまな要望があって、先ほどお話しした追加機能であるデータのソート機能だったり、ピボットしたデータのダウンロードやエクスポート機能だったり、パフォーマンスの改善だったり。これらの機能を取り込んだあと、このライブラリをオープンソースとして公開してみてはどうかという話があって、結果的にこの開発したものはvue-pivot-table-plusとして公開されることになりました。

私自身の感想になりますが、当時アルバイトとして仕事をしていた私にとって、自分が導入した機能に反響があって、あとは要望が届くということにとてもワクワクしたことを覚えています。またこのオープンソースを公開すること自体も初めてだったので、非常にいい経験ができたかなと思っています。

開発前のライブラリ検討

それでは後半に入りまして、開発にフォーカスして、どのようにvue-pivot-table-plusを開発したかについてお話をします。最初にライブラリの検討についてです。OASISとyanagishimaにピボットテーブルを導入するとなった時に、最初は公開されているライブラリを導入して終わりにしよう、という予定でした。なので最初は、ライブラリ探しから行いました。

まず両者ともVue.jsとBootstrapをベースにしているため、これらに導入できて、またデザインも馴染むものを、というものを探しました。同時に導入先の1つであるyanagishimaがオープンソースだったため、そちらへの導入も見越して有料ライブラリではなくオープンソースとして公開されているものを選びました。結果見つけたのが、vue-pivot-tableというライブラリでした。

こちらがvue-pivot-tableのスクリーンショットなんですが、見た目はBootstrapのテーマそのままであって、なので同じくBootstrapのデフォルトテーマを使っている社内ツールの外観に非常にマッチしており、導入を決めました。

vue-pivot-table導入後の問題点

しかし、いざ実装してみるといくつか問題が生じました。こちらの3つが生じた問題なのですが、どれも外からちょっとやっただけでは改善が難しかったため、結果的にForkして開発を進めることになりました。それぞれ軽く説明をしていきます。

まずは余白が既存画面と合わない点です。左がOASISのテーブル表示の既存の画面で、右がvue-pivot-tableのスクリーンショットです。比較すると、セルのパディングが非常に広くなっています。またOASISは、複数のパラグラフを2列表示したり3列表示したりといったように、表示できる領域が非常に小さくなりがちなことから、もともとのピボットテーブルからボタンやパディングを小さくする必要がありました。

これを調整した結果が、右のスクリーンショットです。パディングを狭くして、またヘッダ色を同じにしたことによって、より統一感を出せました。

次がピボットした状態を保存できない。すなわちピボットの状態であるパラメータを取り出す方法がなかった点です。OASISはレポート作成ツールのため、ピボット操作した結果を保存してそのままのかたちで共有できる、再び見せられることが必要です。しかし元のコードでは、左のスクリーンショットのように、それぞれピボットテーブルのパラメータについて初期値を渡すことしかできませんでした。

そこでvue-pivot-table-plusでは右の画像のようにv-modelを利用して、左でいうfieldsをv-modelに書き換えることによって、ピボットテーブルを操作するのにパラメータの更新を親側でキャッチして、それを保存するかたちにすることによって、状態を保存できるようにしました。

また、データ数が多い場合のパフォーマンスも問題になりました。データが小さいうちは問題ないのですが、OASISでは最大1万行のデータを扱うこともあって、データが大きい際には数秒、長いと10秒近くブラウザフリーズが発生することもありました。このスクリーンショットは、大きなデータを集計した際のChromeで計測したパフォーマンスですが、集計にこの前半の部分で集計で4秒、後半の部分で描画に2秒かかってしまっています。

いろいろ原因を探して改善を試みたのですが、もっとも大きかった改善がcomputed propertyに関わる部分でした。よくよくこのパフォーマンスの中身を見ていくと、大量のaddDepという関数や大量のreactiveGetterという処理が実行されていました。それぞれ非常に短いですけど、よく見ると、これが大量に実行されていて、結果すごく長くなってしまっていると判断して、それを調べてみて、computed propertyによるオーバーヘッドなんじゃないかという判断をしました。

元のコードでは集計の途中で使うデータをすべてcomputed propertyとして保存していました。しかしcomputed propertyは初回の計算時に元となったデータを依存先に登録する処理が入ったり、キャッシュから取り出す処理が入ったりと、いくつかオーバーヘッドがありました。

このオーバーヘッドが、元データが大きいほどたくさん実行されることによって、大量のオーバーヘッドになって、描画を含めてかなりの時間を消費してしまう状況だと判断しました。

改善策としては、computed propertyを利用せず、集計自体はmethodを使って行いました。再計算のトリガーは、ピボット操作のパラメータをウォッチして、その中で行うようにしました。

この変換によって、ある例では処理時間をおよそ10分の1まで削減できました。

vue-pivot-table-plus公開後の反応

以上の機能を実装して、vue-pivot-table-plusとして公開したのですが、OSSとして公開したあとは、issueが届くなど反響がありました。例えばこちらは「データをダウンロードする際のファイル名を共有できるようにしたい」というissueでした。これも、私自身の月並みな感想ですが、ちゃんと公開されているんだなという実感をもてました。

またダウンロード数なんですが、めちゃくちゃダウンロードされている……なんてことはなくて、npmのサイトを見ていると、毎週数十件ぐらいのダウンロードはあるようです。ピボットテーブルというマイナーな領域なので当たり前なところではあるんですが、自分はあまりここらへんに詳しくなくて、このダウンロードが本当に使うためにダウンロードされたものなのか、あるいはボットによるものなのかは、ちょっと自分はわからなかったです。

ちなみに右が本家のダウンロード数なんですけれども、基本だいたい負けている状態です。さらについ最近なんですが、本家のほうは最近数百ダウンロードまで跳ね上がったところがあって、これが一過性のものかはわからないんですが、こちらも「plus」を名乗っている以上、負けていられないなという気持ちです。

vue-pivot-table-plus今後の改善方針

では最後に今後の発展の話をしていきたいと思います。今後の改善方針としては3つほど考えています。カスタマイズ性の向上、Vue 3、Bootstrap 5への対応、TypeScript対応です。それぞれ詳しく見ていきます。

まずカスタマイズ性の向上についてなんですけど、現在vue-pivot-table-plusのデザインやパーツの配置などは、主に社内のプロダクト向けに合わせてあります。オープンソースとして公開されている以上、このカスタマイズ性を向上させて社内だけじゃなく、さまざまなプロダクトで利用できるようにしたいと考えています。

具体的な策としては、例えばslotをもっと多用して、独自のデザインを導入できる箇所を増やしたりとか、デザインをカスタムするプロパティを追加することで、カスタマイズ性が向上できると考えています。もともと、このvue-pivot-table-plusの開発が始まったのも、ボタンサイズや余白を調整したいというモチベーションから始まっているので、やはりこのカスタマイズ性というのは、汎用的なライブラリにする上で非常に大切なことだと思っています。

次はVue 3、Bootstrap 5への対応です。ライブラリを公開してから1年以上経って、ついにVue 3とBootstrap 5が公開されました。vue-pivot-table-plus自体は現在どちらも対応していないため、対応できるように修正をしたいと考えています。ちょうど先ほど花谷さんからVue v3のライブラリについての発表があったので、ぜひ参考にしたいと思います。

また、ただ対応を書き換えるだけじゃなくて、最新の機能を用いて改善していきたいと思います。例えば現状ピボットの操作状態をすべて1つのv-model、fieldsという変数で受け取っているんですが、この画像の右ですね。中身はavailableFields、rowFields、さらにこの下にcolFields、ソートの状態など、さまざまなオブジェクトが深くネストされた状態で格納されています。

このためちょっと複雑になってしまっている状況があるので、これをVue 3で仕様変更されて、1つのコンポーネントに複数利用できるようになったv-modelを使って、パラメータごとにv-modelを配置することによってわかりやすくできるのではないかと考えています。

最後にTypeScript対応です。Vue 3がTypeScriptで書かれることが多いので、ぜひ対応したいと思っています。1つ前でも触れたんですが、現状のピボットの操作状態のステート、fieldsの中身が複雑なため、型を用いることによって使いやすくできるのではないかと考えています。

最後にまとめを示して発表を終わります。ご清聴ありがとうございました。

質疑応答

司会者:坂口さんありがとうございました。お疲れさまでした。それでは今またみなさんから質問が届いていますので、ぜひ回答していきたいなと思っております。最初の質問ですが、「プロジェクトでBootstrapを使用していない場合、vue-pivot-table-plusを利用可能なのか」という質問が来ていますが、いかがですか?

坂口:そうですね。一応vue-pivot-table-plus自体はBootstrapを含んでいないので、改めて導入するプロジェクト側でBootstrapをインストールする必要は、dependencyとして追加する必要は今のところありません。そのプロジェクト自体にBootstrapを適用しなくても、vue-pivot-table-plusだけに適用するかたちでやれば、できることはできます。

司会者:わかりました。ありがとうございます。次の質問が「Tailwind CSSとかいろいろなCSSのライブラリがあると思うんですけど、Bootstrap以外で何か対応を計画されているものがあるか」という質問です。

坂口:今のところ計画はないですが、カスタマイズ性の向上という今後の発展の一環として、1つの方向性として具体的なBootstrapとかTailwind CSSといったCSSフレームワークからCSSフレームワークを切り離すようなかたちで、slotなどを利用して引き離すことはできないかということは考えてはいます。

司会者:なるほど。一応工夫はされているという段階ですね。

坂口:工夫をしていきたいなという考えはあります。

司会者:わかりました。ありがとうございます。それでは3番目の質問なんですけど、今回はOSSで公開をされているというお話でしたが、「OSSを公開する時、一番大変だった業務はどういったところなんですか?」という質問が届いています。

坂口:強いて言うなら、OSSとして公開する際には、社内でチェックを通す必要があるので、その手続きといった部分で何回かやり取りをしたので、そこがやはり時間がかかったところではあります。

司会者:ちなみにライセンスは今何を入れているんですか?

坂口:Apache 2.0ですね。

司会者:なるほど。ありがとうございます。それでは最後の質問ですが、「Vue 3対応について日程など予定されているのか」という質問が届いていまして。いつぐらいにアップデートされるのでしょうという質問です。いかがですか?

坂口:正直Vue 3対応の話を考えたのも、やはり今回発表する機会をいただいたということもあって、完全にまだスケジュールが立っているという状態ではないですが、長くても年内には。Bootstrap 5も出ましたし、年内には対応していきたいなという気持ちです。

司会者:回答ありがとうございます。それではみなさん、Vue 3が年内に出るということなので、みなさんお待ちしていただければと思います。坂口さん本当にありがとうございました。お疲れさまでした。

坂口:ありがとうございました。

司会者:ありがとうございます。