アイスタイル特設サイトにおけるVue.jsの導入事例

久保田賢二朗氏(以下、久保田):本日は「アイスタイル特設サイトにおけるVue.jsの導入事例」という話をしようと思います。

Profileです。私、久保田賢二朗と申します。R&D部に所属し、先月やったLaravel JP Conferenceの副実行委員長をやったり、RoppongiDesignersのメンバーをやっています。

PHPはLaravelやPhalconを使ったり、最近はScalaを書いているので、こちらの知見が弱くなっているのですが、フロントエンド開発の話をしたいなと思います。

弊社の紹介を挟ませていただきます。

株式会社アイスタイルというところで、「@cosme(アットコスメ)」という、コスメの口コミレビューサイトを運営しております。いきなり言っておきますが、今日はLaravelの話はありません。すみません。

「@cosme Beauty Day 2018」という企画が弊社でありまして、その特設サイトでVue.jsを使った話をします。

このイベントは何なのかというと、国内最大級、1,900ブランド、35,000アイテム、それが一日限りで20パーセントポイント還元というキャンペーンです。

全国の58局に11月27日から12月4日までテレビCMもしました。

なぜここでVue.jsを使ったのかというと、弊社の導入事例があったのと、VueCLIで開発環境を構築するがDXがすごくよかったのと、社内にすでにVue.jsによるコンポーネントがいくつかあって、それが使えるのでいいんじゃないかというところと、僕が個人的にVue.jsが好きなので、勝手に入れました。

特設サイトの要件

特設サイトの要件ですが、CMによるスパイクアクセスが見込まれるんじゃないかというところがありました。

ディザーサイトは11月1日から公開で、19日になると事前予約ができるようになります。当日販売する商品を事前に予約をしておくと、当日以降に配送されるものです。19日以降になるとキャンペーンページが変わって、毎日表示されるトップページのアイテムが変わるという動的要素があります。

12月3日、4日の当日は、数時間おきにアイテムが変わるというものです。レシポンシブデザインではなかったので、PCとSPのテンプレート両方が別々です。という感じの要件でした。

スパイクアクセスが見込まれると聞いていたので、全部AWS上でやりたい。ということで、こんな感じのアーキテクチャで作られてます。データは、EC2で立てたElasticsearchに格納してあります。フロントは、S3においたVueとかstaticファイルがありまして、それをCloud Frontで配信する感じです。

APIはAWS Lambdaを使ったREST APIとなっています。Elasticsearchに格納されているデータが、その期間に販売される商品しか入れてない感じになっていて、サイトで利用する画像パスやテキストみたいなのが一切入っていない状態となっています。

ということは、ほとんどは静的ページを書き出さないといけない要件になっていました。

目玉商品をピックアップページや、著名人のインタビューページなど、日ごとによって表示されるページが変わるといった動的要素があります。

なので、ツライツライ実装をしまして......。

分かりますかね? 日付ごとにディレクトリを持ちまして、中を見るとコピーみたいのがいっぱい入っているんです。

「すごいな」って今でも自分で思うんですけど、こんなことしました。

この日時が訪れると、LambdaでprivateってS3のディレクトリに入れているやつを、その日時のやつだけをpublicに上書き! みたいなスクリプトを書いてやっておりました。capistranoみたいなイメージです(笑)。すごい疲れます。

先述したように、似たようなページデータが重複します。これは管理がツライなぁ、と。こんなので開発できないだろうと思ったので、Vue.jsは出てこないんですが、EJSを使って、ある程度のパーツをテンプレート化して、gulpでビルドしたときに日別のディレクトリに配置されるように作る、それをマスターブランチにマージされたら、GitLabのCIでS3にputされるみたいなタスクを作っておきました。

EJSにしたところで管理はつらかったですが、このカオスよりはマシなディレクトリ構造でやっていました。

これがタスクの苦労の跡なので、よければスライドを見てください。

Vue.jsを使っているところ

「Vue.js出てきてないぞ」みたいな感じですけど、使っています。

検索ページと商品詳細ページで、赤枠のところは大体Vue.jsが使われています。難しいことは何もしていないですが、URLのクリエパラメータで、そのパラメータを使ってLamdaで用意した商品検索APIをコールして、検索一覧を表示、ページネーションがある感じのページです。

あの星(レーティング)もコンポーネント化したりしていました。

商品詳細ページも、同じように、クエリパラメータ取ってきたら、APIを叩いて生成。カートに入れるボタンとか、商品の画像もホバーすると、サンプルは同じになっているんですが、本当は別々の商品が並んでいるんですが、それをホバーするとメイン画像が変わるようなものもVue.jsで作ってます。

我々の会社は結構こういう開発が多くて、各コンポーネントごとにVueのインスタンスを作っています。これは、クラスのv-product-detailのクラスが付いているdivタグです。あったらこれに対してVueのインスタンスを作ってWebComponentsっぽい感じで使うことが多いです。1ページ全部がJavaScriptのようなSPAをVue.jsを組むということがなくて、古き良きポータルサイトみたいな部分もあるので、パーツパーツでVue.jsを使っています。

ロジックのあるボタンをVue.jsでコンポーネント化

今日はLaravel/Vueと書いたのですが、弊社はVueだけでなく、CakePHPやzend Framework、phalconなど色々なフレームワークを使っているので、基本的にサーバサイドに依存しない感じでWebComponents風な使い方をしております。

ロジックのあるボタンとかもVue.jsなので、サクッと作れました。

例えばクリックした瞬間には、1発目はcookieをくっつけて送ってtokenを取得し、そのtokenを使ってカートインする挙動もVue.jsで簡単に作れます。

PCとSPでデザインが違ったので、さっきMixin怒られちゃいましたが、Mixinを使って似ている商品ページの処理を共通化したということで、すごく楽でした。

各デバイスに向けてビルドするときに、このvue-cli-serviceというコマンドがすごく便利で、この--target libと指定すると、Vueのランタイムが外された状態でビルドがされます。なのでHTML見るとvue.runtime.jsを読み込む必要があります。

運用とその後

トラブルなく終了しました。「ん!?」みたいな(笑)

実はちょっとトラブってました。

Yahoo!のニュースに載っちゃったというやつなんですけど、特設サイトは落ちてないです。あの構成で落ちてたら逆にびっくりするんですけど、落ちませんでした(登壇者注:別の関連サービスが落ちてしまい一時サービスを停止していました)。

まとめです。

Laravelじゃなくてすみません。Vueの話もたいしてしていないですが、VueCLI凄いいいな、と思っております。ESLintとかPrettierとかJestとかは最初から入っているので、質の高い開発ができたのではないかと思います。Vue.jsは大規模なNuxtだったり、WebComponentsみたいなコンポーネント単位で作れるといった幅広いフレームワークなので、こういう突発的な企画でも活躍できます。

おまけです。

Vue.jsを使ったところはSPAっぽい使い方をして、metaタグ回りの変更とかがJavaScriptで書き換えてもSEOとして意味ないがです。なので、OGPの設定も何もしていない状態で。Lambdaでいい感じにできたのではないかと反省がありました。

ご清聴ありがとうございました。

(会場拍手)