必要に応じて共通部分をインストールするだけで完了

平山大暉氏(以下、平山):ジェネレータが実際にどのような動作をして、どのように開発が行われているのかについて話します。

ジェネレータは非常にシンプルな構造になっています。ページ構造の部分がFensi独自の「ページ定義」というJSONで管理されているので、開発するのは主に見た目の部分であるジェネレータ内のComponentsです。

共通部分は先ほど見せた「kit」と呼ばれるGatsby Theme群で管理されているので、必要な機能に応じてインストールするだけで完了します。したがって、フロントは見た目の部分に集中して開発ができます。

実際に使われているkitで例を挙げると、コンテンツログの処理や全体でよく使う共通部分を「gatsby-theme-fensi-kit-core」という名前で開発しています。ページ定義であるJSONデータをもとにGatsby内でページを作成する「gatsby-theme-fensi-kit-template」があります。

ここには出てないんですが、サービスの中にはアカウント管理やログイン・ログアウトを行うサービスも当然出てくるので、ログイン・ログアウトの認証処理を担う「gatsby-theme-fensi-auth」などもあります。

中でも「gatsby-theme-fensi-kit-template」は、CAMが新規開発をするうえで大きく影響しています。このThemeをジェネレータ側でシャドーイングすることで、見た目だけを開発する仕組みを実現しています。

先ほどComponentsを開発するだけと説明したんですが、実際は「gatsby-theme-fensi-kit-template」のComponents配下をシャドーイングして、開発を進めています。ちょっと長いので「kit-template」と略しますね。

kit-templateがどのようにシャドーイングされて、ページが生成されているのか、流れを追ってみます。

これは実際にFensiを使ってサイトができるまでのフローです。Fensi Platformを使用すると、ここまで開発がシンプルになります。

ジェネレータが切り替えでコンポーネントの見た目も切り替わる仕組みを実現

Gatsbyには、ページ作成するまでのライフサイクルにいくつかのAPIが用意されているので、基本的にはこの流れに任意のタイミングで処理を書きます。

今回のフローを当てはめるとこんな感じです。実際はもっと細かく処理を入れていますが、大まかな流れを理解してもらうために2つにしました。この2つの処理も共通する機能なので、Gatsby Themeを使います。

Gatsbyのライフサイクルの説明は割愛しますが、sourceNodesというページを作る前のタイミングで、gatsby-source-fensi-backend-mainというプラグインを用いて、Fensiからページ定義のJSONデータを取得してGraphQLに格納します。

次にcreatePagesの作成のタイミングで「gatsby-theme-fensi-kit-template」を用いて、GraphQLで取得したJSONをもとにJSXを作成します。これをGatsbyでコンパイルすることで、最終的に静的なHTMLとしてページが作成されます。

「このJSXの中身はそもそもどこに書くの?」という疑問が生まれると思います。なぜなら、このJSX内にあるReactコンポーネントはkit-template自身がもっているので、使い手であるジェネレータは常にkit-templateに用意されたコンポーネントしか使うことができないからです。

仮にここでコンポーネントの中身を定義してしまうと、すべてのサイトでまったく同じコンポーネントを使わなくてはいけなくなります。

そこでシャドーイングを使います。「Fensiからのページ定義情報からJSXを作成する」という処理を共通で使用して、実際にレンダリングするJSXの中身はジェネレータ側から作成して使用したいという、今回の問題にうってつけでした。

Fensiのボードの概念に則ったボード群が、kit-templateのsrc配下にあるcomponentsから提供されているので、使い手側であるジェネレータのsrc配下に配置して、シャドーイングします。今回はテキストコンポーネントの中身をジェネレータ側で上書きしたいので、src配下に同じパスでファイルを作成します。すると、kit-template内の対象のファイルがシャドーイングされて中身が上書きされます。

これがシャドーイングすることを想定したコードのサンプルです。kit-templateの内部に配置してあるシャドーイングされるファイルは、中身は空に近い状態で作成しています。サイトが生成されるときは、ジェネレータのsrc配下にある対象のファイルに置き換わって表示されます。

ジェネレータ側で見た目をシャドーイングできるという性質を活かして、ジェネレータが切り替わると、コンポーネントの見た目も切り替わるという仕組みを実現しています。各ジェネレータがそれぞれにシャドーイングをすると、このように各ジェネレータの見た目を切り替えられるので、ジェネレータ側にシャドーイングするファイルを作成するだけで、私たちはサービス開発ができます。

ページ定義と、実際の画面を見ながら説明するとよりわかりやすいと思います。今出ている画面が同じテキストコンポーネントでできている画面なんですが、見た目が大きく異なっていることがわかります。CAMではこの技術を使って、これまでにさまざまなサービスを爆速でリリースしています。

共通部分の積み上げでリリースまでの期間がどんどん短縮

実際にどのぐらいの速度で開発できたか、これまでリリースされた占いサイトをタイムライン形式で図にすると、このようになります。

「CHIE スピリチュアル日和」がおよそ6ヶ月、「星ひとみの天星術姓名判断」は3ヶ月、「奇跡予言 バラート・クラーラ」は2ヶ月、「木下レオンの帝王吉方占い」は1.5ヶ月でリリースと、だんだんとリリースまでの期間が短くなっていることがわかります。サービスをリリースするごとに共通化が進むので、今後はリリースを1ヶ月を切ることもできるのではないかなと思っています。

まとめです。初期の頃はThemeが充実していなかったため、Themeを泥臭く一つひとつ作成していました。サービスをリリースするごとにThemeが充実して、どんどん速く開発できるようになっていて、功を成してきているなと感じます。今後も泥臭く共通部分を積み上げていって、サービスをより早く届けられるように努めたいと思います。ご清聴ありがとうございました。

見た目の共通する場所や部品は独自のUIライブラリで管理

司会者:ありがとうございました。すごい。戦うたびに強くなっている感がします(笑)。

平山:そうですね(笑)。

司会者:日に日に泥臭くレベルアップしているプロダクト感があって、すごく勉強になりました。ありがとうございました。

それでは、このセッションに関するAMA(Ask Me Anything)の時間とします。

ちょっと気になったワードがあったので質問します。Gatsbyやシステムを開発するうえで「ここは魔改造したなぁ」的なところがあれば教えてもらいたいなと思うんですが、なにかそういうのはありましたか?

三好良弥氏(以下、三好):いろいろなところで共通化しているという話がさっきもあったと思うんですが、SEO周りなどを共通化していくと、「あそこではなにをやりたくて、ここではなにやりたい」という要望が共通化しているのにどんどんズレていって、全部に対応したものを作っていった結果、SEOの共通部分がけっこう大変なことになるというのはありますね。

司会者:なるほど。その大変なところを具体的にどのように解決しているのかちょっと気になりますね。

三好:だいたいは追加して解決しています。対応していないというのは自分たちの確認不足で、SEO対策はすべてがだいたい良くなる方向につながっているので、基本的には対応するという方針でやっていった結果、そこの部分に関してのコードがけっこう大変なことになりました。

司会者:なるほど。良い言い方をすると、カバーできる範囲が増えた感じになるんですかね。

三好:前向きに捉えるとそうですね。

司会者:関連した質問なんですが、シャドーイングという方法で、見た目の部分だけに集中して開発されていると思うんですが、見た目の部分に関する工数削減に対して、なにかチームで工夫されているんですか?

平山:今スライドに出てるんですが、4サービス目ということで、やっぱりどうしても同じ見た目のコンポーネントが共通のサイトで出てきたりするんですね。

これは「marouge」というサービスなんですが、「marouge UI」と呼ばれる独自のUIライブラリを僕たちは作り出していて、そこに見た目の共通する場所や部品を置いて、新規サービスごとに「このコンポーネントは共通のやつだから使えるよね」みたいな感じでそこから取り出しながら開発しているので、見た目の部分も徐々に共通化しています。

司会者:これもまた日に日に力強くなっている感がして、すごく良いですね。

平山:そうですね。今のところどんどん速く開発できるようになってます。

司会者:Gatsbyをコアに使われているということなんですが、逆にGatsbyで対応が難しかった例はなにかありますか?

三好:自分たちの設計している考え方が「共通部分を作っていく」なので、Gatsbyで厳しかったというよりは、Themeを使っていて厳しかったという感じですかね。

司会者:Gatsbyで実現が難しかったという例は特にないんですね。

三好:そうですね。Gatsby自体の制約で何か問題が起きているというのはあまりないですね。

司会者:なるほど、それは勉強になります。 ジェネレータがこれからどんどん増えてくる想定で開発していると思うんですが、開発していくうえで、依存ライブラリのバージョンが変わっていったり、増えていったりすると思うんですが、アップデートのしやすさや管理のしやすさを考えていたりするんですか。

平山:つい最近まで、ジェネレータは1つのレポジトリで開発していたので、モノレポジトリというかたちでやっていました。そのあと、それぞれのサイトで機能を追加したり、リリースしたりするタイミングがあり、開発に関係する人たちがどんどん増えたので、やっぱりモノレポジトリで管理するのが徐々にきつくなってきて、レポジトリを分けたんですね。

その際に、依存関係もそれぞれのレポジトリがもつようにしているので、以前はその依存関係が干渉してうまく動かないなことがあったんですが、今はだんだんなくなっているので徐々に良くなっています。なので、ジェネレータごとに管理している状態です。

司会者:ありがとうございます。最終的にGatsbyを使うのを決めた理由や、逆にGatsbyにたどり着くまでになにかほかの設計を考えていたりなど、裏話が聞けたらすごく楽しそうだなと思いました。

三好:Gatsbyにたどり着くまでですね。もともとCAMでは、FensiというWeb Componentsで開発を行っていたんですが、だいたい2年前に「このままWeb Componentsでメンテナンスしていくのは難しい」と社内の話がまとまりました。

HeadlessCMSがあるので、そのタイミングで「静的サイトジェネレータを使ってなにかできないか?」と話し合った結果、Reactベースでドキュメントも豊富だという理由で、Gatsbyを選びました。

司会者:開発のしやすさも踏まえてですか?

三好:そうですね。ドキュメントが豊富というのが、やっぱり一番大きいと思っています。

次の目標はリリースまで1ヶ月を切ること

司会者:さっき触る人が増えてきたという話があったと思うんですが、開発当初と今とでは、開発メンバーの人数の差がけっこうあるんですか?

平山:そうですね。ここ2年ぐらいでけっこう増えましたね。最初は5~6人だったのが、今は2倍くらいです。それこそ三好くんだったりも入ってきて、けっこう大所帯になっています。

司会者:ちなみにこれからはどのぐらいの開発期間になると予測されていますか? ゼロになりますか?(笑)。

平山:(笑)。そうですね。ゼロに限りなく近くするのが一番の理想ではありますが、徐々に徐々に、どこまでいけるかというところ……でも、テイストが大きく変わらないものであれば、本当にどんどん速くなっているので、まずは1ヶ月を切るのが目標ですかね。

司会者:ありがとうございます。1プロダクトを新しく作り上げるのが1ヶ月を切るってなかなかすごいスピード感ですね。共通化って、コアな部分の実装の変更があったときに、その変更の影響箇所がけっこう広くなるじゃないですか。そういうときに安定稼働させるためにやっている工夫はなにかありますか。

三好:先ほど10人ぐらいで開発していると言ったんですが、共通化している影響で、基本的に10人全員が全サービスを触れる状態が今できあがっています。サービスについて全員が理解している状態なので、「コア部分をこう変更したから、こう修正してね」と言えば基本的に誰でも直せるという状況です。若干人に依存してるんですが、そういう状態を作り上げるというのは解決策の1つなのかなと思っています。

司会者:触らなきゃいけない状況なんですね。

三好:そうですね(笑)。

司会者:でもそのおかげで属人性が排されて、すごく安全な開発体制になっているのですばらしいなと感じました。変更に対して実際に稼働しているサービスが正しく動いているかのチェックは自動化されているんですか?

三好:今のところはまだ自動化はできていません。今後はテストも実装していく予定です。

司会者:この共通化プラットフォームの成長に期待ですね。ありがとうございます。お時間が来たので、ここでAMA(Ask Me Anything)の時間を終わりにしたいと思います。あらためて、三好さん、平山さん、ありがとうございました。