てくすた

ピクスタ株式会社のエンジニア・デザイナーがつづるよもやまテクニカルブログです

音楽素材販売プロジェクトで React を小さく導入した話

エンジニアの id:cheezenaan です。いよいよ秋本番ですね。私は近ごろ映画鑑賞して過ごすことが多いのですが、なかでも『劇場版 響け!ユーフォニアム〜届けたいメロディ〜』はこの数年で一二を争うアニメ映画ではないかと絶賛しております。

さてピクスタでは先日のプレスリリースの通り、新たに音楽素材の販売を開始いたしました。昨今需要の高まりつつある動画やアプリをはじめとするコンテンツの制作等、さまざまな用途にご利用いただけます。

f:id:cheezenaan:20171023124622p:plain

pixta.co.jp

この記事では、プロジェクトの舞台裏のひとつとして、音楽素材の検索ページのフロントエンドに React を小さく導入した話をご紹介します。

経緯と導入の方針

ピクスタでは、フロントエンドの JavaScript 開発に Knockout.js や jQuery といったライブラリを採用していますが、昨年冬より一部の機能・ページに対して、React による UI 構築、Redux による状態管理、そして Flow による静的型チェックの導入をはじめています。

React を導入した理由は以下の通りです。

  • メンテナンスの容易さ
    • コンポーネント単位で UI を構築するので、再利用性が高い
    • 外部から渡されるパラメータが同じであれば同じ UI が生成されるため、テストもしやすい
  • ライブラリのエコシステムの活発さ
    • Storybook や Enzyme など、コンポーネントのデザイン確認やテスト用のライブラリがOSSで公開されており、かつ頻繁にアップデートが行われている

Flow を導入したのは、コンポーネント内のデータや振る舞いの情報を説明するドキュメントして活用する意味合いが強いのですが、PropType による動的型チェックと比較して、静的型チェックではコードを実行しなくてもエラーやバグを検知できるため、「実装→確認→修正」のフィードバックをより素早く回せて非常に便利です。

JavaScript へ静的型チェックを導入する選択肢として TypeScript もよく挙げられますが、既存のコードベースへ段階的に展開しやすいこと、ESLint ら既存のツールチェインやライブラリとの相性がよいことから Flow を採用しています。

本プロジェクトのキックオフで「音楽素材の検索ページのフロントエンドでも React を導入しよう」という話が出た際、Redux に関しては業務要件や開発スケジュールを鑑みると、導入・学習コストに対してオーバーキルそうだと導入を見送り、React と Flow のみで UI を構築していく方針に決定しました。

検索ページへの React 導入

既存サービスの機能拡張とはいえ、UI やデザインを含めたフロントエンドの改修は新規開発の色合いが濃く、サーバサイドの修正に比べてコードの修正量が自然と多くなりがちです。

そこで、コードレビュー時におけるプルリクエストの差分が大きくならないように、段階を踏んで実装を進めていきました。

  1. デザインモックから React コンポーネントへの切り出し・分割
  2. React コンポーネントの状態管理

以下では各段階の補足事項や苦労話を解説していきます。

React コンポーネントの分割

f:id:cheezenaan:20171023143644p:plain f:id:cheezenaan:20171023173214p:plain

デザインモックの各要素を、UI の振る舞いの定義と props の受け渡しを行う Container Component と、受け取った props をもとに UI を描画する Presentational Component に大別しながら、React コンポーネントを作成していきました。これら2つのコンポーネントに関する解説は、Redux の作者である Dan Abramov 氏のブログ記事を参照ください。

medium.com

React コンポーネントの状態管理 〜素材の試聴機能を例に〜

音楽素材の検索ページでは、検索結果に表示された各素材の音源を試聴できます。

ピクスタでは、音源視聴ライブラリに mediaelement.js を採用しています。mediaelement.js とは、HTML5 の video / audio タグをラップして動画や音源の試聴プレイヤーをクロスブラウザで提供するライブラリで、ピクスタでも既に動画素材のプレビュー機能で利用しています。

このライブラリの内部では試聴プレイヤーの DOM 要素が React とは独立して生成・管理されており、「ライブラリ内部のプレイヤーの状態と、React コンポーネント内の状態をいかに同期するか」に頭を悩ませました。最終的には React で用意されている ref を用いて、ライブラリで生成した DOM 要素(mediaelement のプレイヤー)を React コンポーネントから呼び出して解決しています。

まとめと今後の展望

以上、駆け足ではありましたが、音楽素材の検索ページのフロントエンドに小さく React を導入した経緯や苦労話をご紹介しました。「要件を満たしつつも大げさになりすぎない構成で React を導入する」という当初の目標を達成できたのではと自認しています。

一方で「ページの構成要素が複雑化していった際、いかに各コンポーネントの状態を管理していけるか」が今後の課題として浮き彫りになりました。Flux の概念を導入して処理の流れを一方向に定めるのが、この手の課題に対する常套手段ですが、Flux 系のライブラリとして一部ページで先行導入している Redux を採用するか、また Flux を採用せず MobX や RxJS などのライブラリを用いて状態を管理するのがよいか、引きつづき検討・議論を深めていきたいです。

また、今回 React にガッツリ触れてみて、$(element).html(someSelector) などと jQuery で直接 DOM 要素を書き換えていた頃から時代の進歩を感じずにはいられませんでした。とはいえなんでもかんでも React で置き換えればいいという話ではありません。用法用量を守って適切にライブラリを選択する姿勢が肝要です。

* * * * *

ピクスタでは、新しい技術の導入にチャレンジしつつ、持続的にサービスを改善していくことに興味があるエンジニアを募集しています。

We are hiring!

recruit.pixta.co.jp