Laravel/Vue.js勉強会#4開催しました!

こんにちは、SCOUTERの id:kotamat です。

2018/04/25、ITプロパートナーズさんにて Laravel,Vue.js勉強会第四回を開催いたしました。

laravue.connpass.com

今回は転職ドラフトさんよりビールを提供していただきました!

f:id:kotamat:20180426112457j:plain

今回は雨の影響もあり、当日キャンセルの方が多かったのですが、枠を大きく超える60人以上の応募がありました。

f:id:kotamat:20180426113543j:plain

同様connpassの参加者アンケートで、Vue.jsとLaravelを使用しているかどうかを取らせていただいたので、その結果です。

techblog.scouter.co.jp

f:id:kotamat:20180426111600p:plain
Vue割合

f:id:kotamat:20180426111704p:plain
Laravel割合

今回も前回と同じような分布になりました。 前回と比べると、どちらも業務で使用している方とまだ使用していない方の割合が増えているようです!

発表内容

登壇

LaravelとNuxt.jsを業務で取り入れる際に得た知見

www.slideshare.net

f:id:kotamat:20180426112521j:plain

ITプロパートナーズのもりーさん、いさおさんの発表です。 Nuxt.jsとLaravelで開発するときの、便利Tipsを紹介して頂きました。 弊社でもVue dev tools等使っている物もありつつ、SequelProのプラグインなどは初耳でした!

AWSで構築するNUXT.JSのインフラ構築3選

gitpitch.com

f:id:kotamat:20180426112542j:plain

二つ目の登壇は私 松本から発表させていただきました。 Nuxt.jsがもりあがっていて、Nuxt.jsの便利機能等のブログは増えてきているのですが、インフラ構成に関する情報が結構すくないなぁと思っていたので、インフラよりの話をさせていただきました。

Elementのすすめ

speakerdeck.com

f:id:kotamat:20180426112602j:plain

最後の登壇はFabricTokyoの中筋さんから発表。 Elementはドキュメントのみやすさももちろんのこと、便利機能が揃っており、ソースコードも非常に参考になる、素晴らしいUIフレームワークなので、迷ってたらとりあえず触ってみるといいと思います!

以前小平より、使い方の共有もさせていただきました。こちらもご覧ください!

techblog.scouter.co.jp

LT

VueでJSXを使うのはありなのか

speakerdeck.com

f:id:kotamat:20180426112624j:plain

一つ目のLTは弊社エンジニアの小平の発表。 Vue.jsでのJSXの使用は、ケースバイケースで適応していきましょうと言う話でした。 分岐が多いコンポネント周りの出し分けは結構便利になるかと思います!

Laravel 5.6 デフォルトの例外ハンドリング処理をまとめてみた

www.slideshare.net

二つ目のLTはおかしょいさんの発表。 Laravelの例外処理の中身に関して調査した内容を発表していただきました! 若干複雑な中身だなぁとおもっていたので、参考になりました!

懇親会

f:id:kotamat:20180426112720j:plain

今回は懇親会の時間をもうけ、皆さん歓談していただきました! 今回始めて参加された方も、他の参加者の方と打ち解けたようでよかったです。

まとめ

今回もLaravel,Vue.js双方の話が聞けて、盛り上がった会になったかと思います。 次回も開催予定ですので、会場提供、登壇に関しては随時募集しております!

最後に

SCOUTERではVue.js, Laravelをやっていきたいエンジニアを募集しております! 興味があれば、お気軽にご連絡ください! twitterのDMでも大丈夫です! https://twitter.com/kotamats

www.wantedly.com

www.wantedly.com

NuxtMeetup#1を開催しました!

NuxtMeetup#1を開催しました!

こんにちは、SCOUTERの id:kotamat です。 2018/03/28 弊社にてNuxtMeetup#1を開催しました!

nuxt-meetup.connpass.com

イベントではハッシュタグ #nuxtmeetup でつぶやいて頂いたので、そちらをもとにtogetterにまとめております。

togetter.com

イベント内容

Nuxt.jsが最近注目されている中で、気軽に語る場があるといいなぁとおもい、 ビール片手にLTしながらワイワイできるイベントを開催しました。

speakerdeck.com

当日は16名ほど参加していただき、少人数ながら深い話をLT交えて話せたのではと思います!

LT内容

vue-cli 3.0時代のNuxt.js

@andoshin11さん speakerdeck.com

f:id:kotamat:20180329111648j:plain

Vuecliの3.0がリリースされると、新たにプラグインという概念が追加され、簡単に必要なものを必要な分だけプロジェクトに取り入れられるという発表でした。 まだベータ版ということもあり、足りないAPIがあるみたいですが、しっかり整備されてきたら非常に使い勝手のいいアップデートかなと思います。 まだVuecli3.0は触ってないですが、積極的にキャッチアップしていきたいとおもいました!

Nuxt.js でつくるアプリケーションの設計 / Architecture of nuxt application

@inouetakuyaさん speakerdeck.com f:id:kotamat:20180329111654j:plain

あのVuefes.jpの裏側をお話してくださいました! Nuxt.jsで作成されているとのことですが、コンポネントの設計方法やSCSSの置き方等、第一線でVue.jsを使われている方の構成は非常に参考になりました。 UIフレームワークなどの構成を参考にされたとのことですが、各フレームワークも知見の塊なので、構成にまよったらそちらを参考にすることを私からもおすすめします!

Let's generate everything with Nuxt

@miyaokaさん slides.com f:id:kotamat:20180329111717j:plain

静的サイトジェネレーターNuxtentのご紹介をしていただきました。 静的サイトを作成したとしても、SPAで画面遷移するときはAPIが走っちゃうので、そのAPIもキャッシュ化して爆速にしようというアプローチをデモとともにご紹介。 ブラウザのhistoryがぶっこわれるくらい爆速で画面遷移するデモは面白くもあり、それほどコンテンツ量のないサイト(コーポレート等)では応用できそうだなぁと思いました。

懇親会

f:id:kotamat:20180329111602j:plain f:id:kotamat:20180329111730j:plain 懇親会では、PWAの話やコミュニティーの話、SSRでのベストプラクティス等中身の濃い話が多かったです。

まとめ

今回思いつきでNuxtMeetup開催させていただきましたが、参加者の方も濃いディスカッションができ、非常にいい会になったかなと思います。 次回も開催する予定なので、今回参加できなかった方も次回はご参加いただければと思います!

Web サイト制作にこそ Nuxt.js がベストマッチである理由

業務委託でSCOUTERのフロントエンド周りの開発をお手伝いしている、 花谷拓磨(id:potato4d) です。

SCOUTER は、先日自社のコーポレートサイトを Nuxt.js + WP REST API 構成にてリニューアルいたしました。

普段であれば SPA や SSR が必要な高度なアプリケーションなど、主にWebアプリケーション開発の文脈で語られる事が多い Nuxt.js ですが、何故Webサイトであえて Nuxt.js を採用したのか、そしてそのメリットから、実際に利用しての課題点まで、制作を担当した私自ら知見を存分にご紹介したいと思います。

新しいコーポレートサイトのご紹介

f:id:potato4d:20180315110402p:plain

まずは何はともあれ成果物から。

今回のコーポレートサイトでは、 Vue がアニメーションと親和性が高いこともあり、ブランディングサイトとして十分な価値を示せるようにリッチに仕上げました。Webサイトとしての Nuxt.js がどのように動くかも含めて、よろしければ是非一度ごアクセスください。

corp.scouter.co.jp

技術構成

f:id:potato4d:20180315112001p:plain

Nuxt.js 本体のご紹介に移る前に、技術構成もご紹介しておきます。 既にあるサーバーを流用しているので、 EC2 インスタンス上に NGINX と WordPress が載っているところからスタート。 現在利用している技術は以下となっています(前段にNGINXは別途立っています)。

基本的にはほぼすべてを Nuxt.js で賄っていますが、古いコーポレートサイトのお知らせやプレスリリースを WordPress で管理してています。 今後もビジネスメンバーが使いやすいように CMS として WordPress をそのまま残しながらも、開発自体は WP REST API を利用して API 経由で記事情報を取得し、コストをかけずに運用できる形としました。

Express はエッジ利用しており、お問い合わせやエントリーなどの細かなバックエンド API の受け皿としてピンポイントで使われています。

Nuxt.js でWebサイトを作るとなると、大抵の場合お問い合わせのために Express を挟むか AWS Lambda を挟んで generate で静的サイトとしてホストするかの二択になるでしょう。今回は記事ソースが WordPress であり、 SSR は必須のため、 Express としました。

何故 Nuxt.js を採用したのか?

f:id:potato4d:20180315110458p:plain

冒頭でも書きましたが、 Nuxt.js といえばやはりWebアプリケーション、 SPA での開発のフレームワークと思われがちです。

しかしながら、今回はWebサイト制作です。一件オーバーエンジニアリングに見える技術採用ですが、実は全くそんなことはなく、 Nuxt.js を利用することで非常に高い生産性のもとにWebサイトを作ることが可能 です。

以下に、主な採用利用をご紹介します。

コンポーネント指向の恩恵を受けながら、Vue の資産のもと SEO に強い Web サイト構築基盤の活用

やはり何より大きいモチベーションは コンポーネント指向及びモダン JavaScript 文化のもとに Webサイト を構築できる というところにあります。

SCOUTER は主にWebサービスの会社ということもあって、 Web制作の鉄板である ejs や Pug などのテンプレートエンジンと、Sass + 設計パターン(SMACSS や FLOCSS)での開発ということは滅多にありません。 それだけでなく、もはや前述のようなスタックでの、いわゆる従来の「Web制作」まわりのスキルは、 Web サービス開発者視点では、時代から取り残されつつあるものとなっています。

また、 SCOUTER の場合は、コンポーネント指向を中心に据えるために Vue を幅広く使っており、 jQuery によるダーティなアニメーションの実装を行う機会は殆どないため、できれば Vue のアニメーションなどをフル活用したいところです。

しかしながら、 Web サイトとなると SEO, OGP 都合でモダン JavaScript フレームワークは使えないことが多いのは世の常。いくら Google が読んでくれようと、いくら世の中のクローラーが進化しようと、効果の高い TwitterFacebook がきちんと対応してくれるまでどうしようもないですし、 Google ですら、非同期な JavaScript は読んでくれない始末です。

そんな中、 SEO friendly なままに Vue の記法やコンポーネント指向を流用できる Nuxt.js は、まさにWeb制作と救世主となりえる技術でした。 コンポーネントで部品を組み合わせることで今後のエントリー種別の増加なども容易ですし、コードもDOMを直接書き換えないため非常にわかりやすいように仕上げることができます。

Scoped CSS による手軽で破綻しづらいCSS管理

f:id:potato4d:20180315110833p:plain

次の大きな要因として、Scoped CSS の存在が挙げられます。 Scoped CSS とは、Vue コンポーネント内で、そのコンポーネント限定の閉じた CSS を適用できる機能であり、 全てを Scoped で書いてしまうと、基本的に意図しない範囲に CSS があたってしまって壊れるということを避けらる という大きなメリットがあります。

勿論、コードベースが大きくなればなるほど、 Scoped であっても管理をうまくやっていく必要はありますが、こと Web サイトに限ってはそこまで肥大化しないことから、気軽にコンポーネントを切って、 CSS の設計に頭を悩ませる必要なく記述が可能となり、簡単にスコープ内に閉じ込められる強力さがダイレクトに効いてきます。

Node.js 製フレームワークとの親和性

最後に、 Node.js のフレームワークとの親和性が挙げられます。昔のようにレンタルサーバーで PHP が動いていた時代から変わったこともあり、お問い合わせをどのように実装するかは Web サイトの悩みどころの一つです。

静的サイトの場合はロジックをもたせることができないので、サーバーレス的に Lambda で解決する方法もありますが、 Nuxt.js の場合は SSR サーバーが他のNodeフレームワークと連携しやすいという特徴があるので、気軽に機能拡張を Express で行うことができます。

Express と親和性が高いと、特定の処理が差し込みやすくなるので、 SSR サーバーが薄く作られていて他の技術と組み合わせやすいのは大きなアドバンテージとなります。

以上のような理由から、 Nuxt.js の採用に至りました。

Nuxt.js を採用した結果について

そうして実装が進み、完成後の成果物の結果、以下のような良いことがありました。

CMSの手軽さを残したままフロントエンドエンジニアが管理しやすいシステムになった

先述の通り、これまでのコーポレートサイトは WordPress で管理されており、かつデザインの為に様々なプラグインが使われていました。サービスローンチ当初に作られたということもあり、場当たり的なプラグインが多く、フロントエンド・サーバーサイドのエンジニアともになかなか触りがたい独自知識の領域が生まれてしまっていました。

そこを今回のリニューアルによって Nuxt.js へと置き換えたことにより、社内で十分使われている Vue(and Nuxt.js)を利用した環境となり、以前より圧倒的にコードを管理できる人間が増えました。また、開発側は管理がしやすくなっていながらも、 WP REST API という形での WordPress の続投により、非エンジニアにとってはいつもの管理画面を引き続き利用でき、大きな体験の変更なくコンテンツの運用が可能な状態となっています。

ロジックの追加拡張や要素の追加で破綻しづらいWebサイトが完成した

また、技術面でのメンテナビリティの向上も挙げられます。

SPA 、特に Vue の技術を使わないでWebサイトを作った場合、 DOM の直接的な変更や jQuery プラグインCSS 設計などで段々と拡充のコストが大きくなっていきます。 しかしながら、今回は全て Vue で書かれていることにより、見た目の更新もしやすく、また、一部に Vuex を利用することで機能面にも幅を持たせておくことができています。

課題点

一方で、割りと入り組んだ使い方をしているので幾つか課題があります。

特に WP REST API との連携によるものですが、これについて WordPress に限った話ではなく、情報リソースを外部にもたせている場合は等しく起きるでしょう。

Web サイトにおける SSR 内での API 連携のレイテンシ

おおよその場合何よりもネックになるのはここかと思います。

普通であればWebサイトの1ページを読むのに必要なHTTPリクエストは一回であり、他のアセットに関してページの読み込みと同時に多数のHTTPリクエストが走る形となりますが、 SSR 内で API を叩く場合はこの内部での API へのリクエストが一回余分に発生します。

クライアントから SSR サーバーへ、 SSR サーバーから WordPress へとリクエストを送り、その上でデータを返却してきますが、 SSR の結果がでるまでクライアントは他のアセットを読み込むことはありません。 どうあがいても、この段階で最低でも数十〜数百msのレイテンシが挟まってしまうのは課題でしょう。とくに、 WordPress の場合、カテゴリなどの重いデータ取得がある場合は将来的に秒単位で待つことになることも考えると、キャッシュエンジンなどを有効活用するべきでしょう。

また、そもそも WordPress などのように開発陣以外も触ることができるシステムが必要でなければ、 Nuxtentを利用して静的サイトとして Markdown ベースで管理する。といった方法が最も賢い選択であると思います。

WP API の認証付き API の取り扱い

また、 WordPress のような CMS の場合、下書きという概念がついてくるのも厄介です。記事情報の API は Headless なのでプレビューはできれば本番サイトでみたい反面、一般ユーザーには勿論見えては困ります。こうした場合の認証をどうするか。という問題が常に存在します。

この解決は、基本的に以下のどちらかをとることになりますが、どちらをとっても大差はないため、よりメンテナンスしやすいほうをとると良いでしょう。

  • Express などで専用の認証付きルーティングを作成し、そこで Cookie を付与した上で、特定の Cookie を所持している場合、CMS API の Authrization ヘッダーに Cookie の Credential を追加する
  • CMS の管理画面で Cookie を付与した上で、特定の Cookie の場合は CMS API の Authrization ヘッダーに Cookie の Credential を追加する

LocalStorage や IndexedDB では SSR 側に情報を渡すことはできないので、少々泥臭いですがここでは Cookie を使うのがおすすめです。

おわりに

SCOUTERでは、バックエンドはモダンな Laravel であることは勿論、フロントエンドも多くの領域で Nuxt.js が使われており、他にはない新鮮な環境でのフロントエンド開発を行うことが可能できます。もし Nuxt.js を使ったフロントエンド開発に興味があるかたは、是非以下の新コーポーレートサイトへのリンクよりご応募ください!

corp.scouter.co.jp

また、今月末に SCOUTER 主催で Nuxt Meetup が開催されるとのことですので、こちらもよろしければどうぞ!

nuxt-meetup.connpass.com

ソースコードドリブンで作成したLaravelMeetupの登壇資料の裏側

こんにちは、SCOUTERのid:kotamatです。 先日3/8に開催された LaravelMeetupにて登壇させていただきました。

laravel-meetup-tokyo.connpass.com

資料はこちら

gitpitch.com

こちらの発表で使用した発表形式が結構好評だったので紹介したいと思います。

Gitpitchを使ったソースコードドリブン資料作成

今回Gitpitchと呼ばれるプレゼン資料生成ツールを使って発表しました。 GithubなどのGitホスティングサービスにPITCHME.mdを置いておくことで、自動的にプレゼン資料が作れてしまうというものです。

実際の発表資料のリポジトリこちらになるのですが、このように、ソースコードが乗ってる普通のリポジトリPITCHME.mdを設置するだけで発表資料が出来上がります。

URLはhttps://gitpitch.com/$user/$repo/$branchになります

実際に資料作成でやったこと

composer create-projectでLaravel環境を整備

はい、発表資料作成の最初のステップがLaravelのインストールでした。 今回はLaravelMeetupということで、とりあえず何も考えずにLaravelをインストールしGitHubに公開しました。

コードエディターで発表に使うコードを書く

今回の発表では、テストコードの書き方Tipsを発表したかったので、アプリケーション側での動くコードと、それのテストコードを記述しました。 もちろんPhpStormなどのいつも使っているエディターで書くことができるので、自動補完やコードリント等日常やっていることの延長線上でコードを書いていくことが出来ます。

コードをMarkdown上で表現

実際に書いたコードは下記のような形で呼び出すことが出来ます。

---?code=tests/Feature/ApiTest.php&lang=php&title=tests/Feature/ApiTest.php

@[14-16](GETパラメータを定義しておき)
@[18-19](routeの第二引数にパラメータを渡してレスポンス取得)
@[21](ステータス200かどうかチェック)
@[22](取得したデータをprint_rで表示)

codeパラメータに、PITCHME.mdとの相対パスを、langパラメータに言語を指定します。 レンダリングにhighlight.jsを使用しているので、こちらに書いてある言語はサポートされています

@でハイライトする行数を指定することもできます。

コードハイライト

校正ツールの導入

Markdownで記述するので、Markdownを使ったツールの導入も出来ます。

今回は、textlintを導入してみました。 まずはyarn or npmでインストールします。

yarn add --dev textlint textlint-rule-preset-japanese textlint-rule-preset-jtf-style textlint-rule-spellcheck-tech-word 

こちらでインストールしているのは下記のルールです。

  • textlint-rule-preset-japanese
    • ツール作者が作成した日本語関係のルールセット
  • textlint-rule-preset-jtf-style
  • textlint-rule-spellcheck-tech-word
    • WEB+DB PRESS用語統一ルールをベースにしたazu/technical-word-rulesの辞書で単語チェック

次に。textlintrcファイルに各種ルールを使用することを定義します。

{
  "rules": {
    "preset-japanese": true,
    "preset-jtf-style": true,
    "spellcheck-tech-word": true
  }
}

最後にファイル名を指定してコマンドを実行します。

./node_modules/.bin/textlint PITCHME.md

実行すると下記のように、問題の箇所を指定してくれます。 --fixオプションを指定すると、修正可能なものに関しては自動で修正してくれます

PITCHME.md
   13:10  ✔   git => Git                                                                                                      spellcheck-tech-word
   22:57  ✔   でgithub => でGitHub                                                                                            spellcheck-tech-word
   69:3   ✔   句読点には全角の「、」と「。」を使います。和文の句読点としてピリオド(.)とカンマ(,)を使用しません。              preset-jtf-style/1.2.1.句点(。)と読点(、)
   22:32  ✔   一つ => 1つ
数量を表現し、数を数えられるものは算用数字を使用します。任意の数に置き換えても通用する語句がこれに該当します。  preset-jtf-style/2.2.2.算用数字と漢数字の使い分け
    3:15  ✔   原則として、全角文字と半角文字の間にスペースを入れません。                                                      preset-jtf-style/3.1.1.全角文字と半角文字の間
    3:33  ✔   原則として、全角文字と半角文字の間にスペースを入れません。                                                      preset-jtf-style/3.1.1.全角文字と半角文字の間
  108:27  ✔   半角のかっこ()が使用されています。全角のかっこ()を使用してください。                                          preset-jtf-style/4.3.1.丸かっこ()

やってみてよかったこと

  • 実際のコードを書きながら発表資料を作成できるので、タイポやスクショ貼り付け等の無駄な作業が削減される
  • 実行可能なソースコードとして残るので、発表中に消化しきれなかった人でも、リポジトリを見れば再現が可能
  • Markdownで記述できるので、Markdown周辺の技術の適応ができる(lintとか)
  • ハイライトがhighlight.jsをサポートしているので、基本的にどの言語、テキスト形式でもいい感じの見た目になる

ちょっと不満に思ったポイント

  • Githubにpushしないと動作が確認できない(一応Scalaで動いているので、ローカルにインストールすれば動かせそうだけど‥)
  • 画像を含めてpushしてもリンク切れしていることがあった(原因不明)

まとめ

技術系のTipsを発表するような登壇ではGitpitchは非常に使い勝手がよかったです。 GitpitchのWikiを見ると、まだまだ使用していない機能もたくさんあるので、今後登壇する機会があればチャレンジしてみようとおもいます。

最後に

LaraランチというLaravelについて語るランチ会を開催するので興味ある方ご応募お待ちしております! https://techscouter.connpass.com/event/81939/

Laravel/Vue.js勉強会#3開催しました

こんにちは、SCOUTERの id:kotamat です。

2018/01/23、DMM.com Laboさんにて クリエイターズマッチさん、うるるさんご協力の元 Laravel,Vue.js勉強会第三回を開催いたしました。

laravue.connpass.com

f:id:kotamat:20180124123121j:plain
開始前。雰囲気があるとても広い会場です!

今回も今まで同様、定員を大きく超える方々にご応募頂きました!

今回はconnpassの参加者アンケートで、Vue.jsとLaravelを使用しているかどうかをとってみました。

f:id:kotamat:20180124105010p:plain
Vue.js割合

f:id:kotamat:20180124105213p:plain
Laravel割合

どちらも半数以上の方は業務or趣味で使用しているようですね。 両方業務で使われている方も多く、非常に興味深いアンケートでした!

発表内容

登壇

Vueコンポーネントを複数リポ で共通化するためにやったこと

speakerdeck.com

f:id:kotamat:20180124143420j:plain

弊社エンジニアの id:ryotakodaira の発表です。 複数リポジトリでVueコンポネントを使用するために専用のリポジトリを設置、挙動をstorybookを使って実装しており、そちらの発表でした。

Larvel Echo + Vue.js + axiosで簡単チャットアプリ開発

www.slideshare.net

f:id:kotamat:20180124143629j:plain @hukuzatsuさんに発表いただきました。

チャットアプリケーションをSPAで構築するための方法を細かくお話されており、非常にわかりやすい内容でした!

LT

s.kuriharaさん

f:id:kotamat:20180124143730j:plain

BladeとVue.jsを組み合わせたときのハマるポイントについてお話していただきました。 テンプレートの記法が似ているので、ハマるポイントは想像付いてましたが、予想以上に多い印象でした。

RyutaHamasakiさん

f:id:kotamat:20180124143815j:plain slides.com

LaravelとVueでスクラムのベロシティ管理ツールをつくった話をしていただきました。 1週間で構築したとのことですが、機能的にも非常に使いやすそうな印象でした!

mpywさん

f:id:kotamat:20180124143934j:plain qiita.com

Laravelのお役立ちネタということで6つ紹介していただきました。 それぞれLaravelの内部構造を把握し、ハックしているようなネタで、非常に興味深い内容でした!

k-kurikuriさん

f:id:kotamat:20180124143947j:plain speakerdeck.com

Laravel5.6のChangelogの話をしていただきました。 Laravelはさらに業務用ツールとしての機能拡充に踏み切っているなぁという印象でした!

たけなかさん

f:id:kotamat:20180124144002j:plain PHPとVue.jsでExcelの連携ツールを作ったお話をしていただきました。 ExcelまわりはレガシーなOSSがあったりして技術選定難しい印象ですが、フロントでスプレッドシートっぽいUI構築できるOSSの紹介等ためになるお話でした。

まとめ

皆さんLaravel、Vue.js双方掛け合わせというテーマにそった内容を発表していただきましたが、 それぞれのフレームワークだけの勉強会では聞けないような内容で非常に面白い回となりました!

会場をお貸しいただいたDMM.comLaboの皆さん、ご協力頂いたクリエイターズマッチの皆さん・うるるの皆さん、参加者の皆様ありがとうございました!

SwaggerでAPI仕様書に消耗しているなら.restを使うといい。特にLaravelなら

こんにちはSCOUTERの id:kotamat です。

背景

弊社では、LaravelとVue.jsを使ってSPA + APIサーバーの構成でアプリケーションを構築しています。 APIとクライアントを別で実装すると各々を並列に開発できるので、開発効率も上がるのですが、APIのインターフェースをドキュメント化するのにどうしても工数がかかってしまいます。

最近はWebのgRPCが出てきたり、そこまで行かなくてもProtocol Bufferのver3でjson生成してRESTAPIとする等の方法で互いの通信プロトコルを定義するプロジェクトが増えているので、そちらを使うという選択肢もあります。 しかし、Laravelに標準で入っているFormRequestだったり、Eloquentの便利なリレーションの機能を使おうとするとこれらの機能と競合するため、フロントでは純粋なjsonを使う必要が出てきます。

そこで当初はSwaggerを使ってAPIのインターフェースを定義していたのですが

  • 独自記法を覚える必要がある
  • どうしても記述量が多くなる
  • #definitions/スキーマをモデルごとに書く必要がある
  • 細かいカラムの表示制御(あるAPIではemailを含めるが、他のAPIでは情報保護のためにemailは表示しないなど)を表現しづらい
  • API仕様書自体の保守コストがかかり、実装と違う記述になる

という短所があり、うまくワークしませんでした。 Swagger-PHPも検討しましたが、メソッドのコメントに記述する量が膨大で移行コスト対効果は認められないという判断となりました。

エディターベースのAPI定義: .rest

そういった中で、.rest.httpといったファイル形式でAPI仕様書を書くという方法に着目しました。 エディタごとに多少仕様はことなるのですが、RFC 7230ベースでAPI仕様を記述するだけで、実行可能なAPI仕様書を書くことができます。

今まではVimEmacsAtom等のエディタにプラグインを入れる形で上記の環境を整備出来ていましたが、PhpStormやIntelliJIDEAなどのJetBrains系IDEにも2017.3 EAPから公式導入され、よりプログラマにとって嬉しい環境が整ってきました。

この.rest, .http形式で記述することのメリットとしては、

  1. RFC 7230ベースでの記述となるので、見やすく、学習コストが非常に低く、自動出力の実装コストも低い。
  2. 依存関係がないのでファイルの分割粒度をリクエスト単位に分けても問題無い
  3. エディタのサポートがあることで、API仕様書用に環境を整備しなくても実行可能な環境が構築できる。
  4. ローカルファイルに記述するので、セキュリティー等考える必要がない。

があげられるかと思います。 特に1.の自動出力の実装コストが低いというところは、当初のニーズにマッチしていたため、この方法を採用しました。

Laravelのテストとの親和性

弊社ではLaravelというPHPフレームワークを使用しているのですが、LaravelにはPHPの標準UnitテストフレームワークPHPUnitをLaravel用に拡張したテスト用便利機能が実装されております。 特にAPIを叩き、レスポンスをテストする拡張が非常に使いやすく、下記のように記述するだけです。

// GET
$res = $this->getJson(
   "/api/user/" 
);
// POSTなどでのペイロードは第二引数に
$res = $this->postJson(
   "/api/user/",
   ["name" => "hoge"]
);

こちらは単なるクラスメソッドですので、オーバーロードをすることで、リクエスト、レスポンスに対して何かしらのフックを仕込むことが可能です。

ということで簡単なプラグインを作成

プラグインこちら ※プルリクお待ちしております! 使用方法は下記です。 (こちら https://github.com/kotamat/laravel-apispec-sample に実装サンプルを用意しました。diff)

まずcomposer requireでパッケージをインストールします

composer require --dev kotamat/laravel-apispec-generator

その後、上記APIレスポンスのテストケースを書くクラスにて、ApiSpec\ApiSpecTestCase を継承します。

<?php

namespace Tests\Feature;

use ApiSpec\ApiSpecTestCase;
use Tests\CreatesApplication;

class HttpTest extends ApiSpecTestCase
{
    use CreatesApplication;
    protected $isExportSpec = true;
}

ファイル出力するかどうかは$isExportSpecで切り替える事が可能です(デフォルトはfalse)。 envの値で真偽値を切り替えるといいかと思います。

テストケースで下記のように記述し、実行すると

public function testPost()
{
    $this->postJson("/api/test",['hoge'=>'huga']);
}

/storage/app/api/test/POST.http に当該のファイルが生成されます。(下部のコメントアウトされているところは、レスポンスの値となります。) Laravelにおいて/storage配下はGitに含まれないディレクトリとなりますので、生成後のファイルがGit汚染することはありません。

f:id:kotamat:20180123140339p:plain

ためしに、php artisan serve --port 9000http://0.0.0.0:9000にサーバーを立ち上げ

- POST /api/test
+ POST http://0.0.0.0:9000/api/test

としてあげると、

f:id:kotamat:20180123140404p:plain

このように実行結果が帰ってきます。

まとめ

Swaggerに変わるAPI定義書として、.rest.httpを紹介させていただきました。 今回紹介したようにテストケースとして記述しておけば、そのテストが通っている限り、APIの仕様が最新であることが保証でき、副産物としてテストの記述もれの防止やコードレビューでの補助ツールとして大きくプロジェクト品質に貢献するかと思います。

Nuxt.jsとFirebase/Firestoreで動的コンテンツをPWAする

Nuxt.jsとFirebase/Firestoreで動的コンテンツをPWAする

こんにちは、SCOUTERの id:kotamat です。

こちらは Firebase Advent Calendar 2017 - Qiita 23日目の記事です。

先日SafariがPreview版でServiceWorkerを実装したという話もあり、2018年はServiceWorker,それに伴うPWA関連の技術がより注目されそうですね。 私個人的にも注目の技術の一つとしてキャッチアップしておかないとと最近強く感じてます。

前回はNuxt.jsでPWAを設定する方法を紹介させてもらいました。 techblog.scouter.co.jp

今回はさらにDBを使って動的コンテンツをPWAする方法を検証してみたいと思います。 前回のプロジェクトをそのまま使用する前提で話を進めていきますので、プロジェクトの作成等は上記の記事を参考にしてください。

Nuxt.jsについてはこちらを参考に。

techblog.scouter.co.jp

完成イメージ

FireStoreに保存された画像のURLのリストを元に、Firebaseのホスティング上にレンダリング、さらにそのコンテンツをキャッシュさせてオフラインでも閲覧できるようにします。

画像のURLに関しては、外部サイトの画像のキャッシュを実現するため、tumblrの画像URLを使用してみます。

下記のようにオフラインでも画像が表示されれば完成です。

f:id:kotamat:20171223233906p:plain

Firebase用の環境を設定する

Firebaseのcliをインストールする

$ yarn global add firebase

次にFirebase cli上でログインします。

$ firebase login

対話的にログイン情報を求められるので、入力したらcliの設定は完了です。

モジュールインストール

まずは、Nuxt.jsとFirebaseの連携を簡単にするモジュールをインストールします。

$ yarn add nuxt-firebase

こちらのモジュールは、Nuxt.jsのpageコンポネント上でapp.$firebase(), this.$firebase()のような形でFirebaseのインスタンスを呼び出せるものとなります。

Firebaseには設定が必要ですので、webコンソールからアプリケーションを作成後、下記の設定を取得してください。

f:id:kotamat:20171223233915p:plain こちらのjsオブジェクトをnuxt.config.jsに貼り付けます。

+  env: {
+    apiKey: '',
+    authDomain: '',
+    databaseURL: '',
+    projectId: '',
+    storageBucket: '',
+    messagingSenderId: ''
+  },

Firebaseに必要なファイルの追加

今回はFirebaseの機能のうち

を使用したいと思うので、そこに必要な設定ファイルだけ追加します

firebase.json

{
  "firestore": {
    "rules": "firestore.rules",
    "indexes": "firestore.indexes.json"
  },
  "hosting": {
    "public": "dist",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ]
  },
  "storage": {
    "rules": "storage.rules"
  }
}

firestore.indexes.json

{
  "indexes": []
}

firestore.rules

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write;
    }
  }
}

storage.rules

service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write: if request.auth!=null;
    }
  }
}

設定は以上となります

動的コンテンツを生成する

FireStoreに画像のURLを保存していきます。 まずはDatabaseからFireStoreを選択し、使用可能にします。

f:id:kotamat:20171223233929p:plain 次に下記のようにwebコンソール上でデータを追加します。 Valueのところはtumblrから画像URLを取得し、入力します。

f:id:kotamat:20171223233922p:plain

Nuxt.jsのpage上でFirebaseのデータを取得できるようにする

FireStoreではRealtimeDatabaseと同様、オフラインでのキャッシュに対応しています。 app.$firebase.firestore().enablePersistence()という処理を実際の取得処理の前に記述しましょう。

collection('image').get()でデータを取得できるのですが、内部構造は下記のようになっているので、その形で<template>タグ内で画像をよびだします

images:
  docs:
    - data():
      - url: "画像URL"
    - data():
      - url: "画像URL"
    ...

<script>

 export default {
   components: {
     Logo
+  },
+  async asyncData ({app}) {
+    try {
+      await app.$firebase.firestore().enablePersistence()
+      const images = await app.$firebase.firestore().collection('images').limit(5).get()
+      return {
+        images: images.docs
+      }
+    } catch (err) {
+      console.log(err)
+    }
   }
 }
 </script>

<temlpate>

      <div>
        <img
          v-for="image in images"
          :src="image.data().url"
        />
      </div>

本番にデプロイする

nuxt build --spa/distディレクトリにデプロイ用のファイルを生成したのち、firebase deployコマンドでデプロイします。

デプロイが完了すると、https://<projectId>.firebaseapp.comにアプリケーションが反映されます。

デベロッパーツールでオフラインにしても同じように画像が表示されることが確認できるかと思います。

まとめ

Firebase, Nuxt.jsを使うことで、動的コンテンツのPWA化も簡単にできることが確認できました。