Slide 1

Slide 1 text

Copyright © M&A Cloud All rights reserved. Laravelで運用しているサービスを Nuxt.jsにリプレイスする PHP Conference 2020/Track 4 Kenjiro Kubota

Slide 2

Slide 2 text

Copyright © M&A Cloud All rights reserved. Profile 2 久保田 賢二朗 kubotak-is kubotak_public kenjiro.kubota 株式会社M&Aクラウド JavaScript Go PHP https://kubotak.page

Slide 3

Slide 3 text

Copyright © M&A Cloud All rights reserved. PR

Slide 4

Slide 4 text

Copyright © M&A Cloud All rights reserved. 買い手
 ・案件報酬はM&A成功報酬のみ ・最低手数料なし ・売り手ソーシングのチャネルが増える ・M&Aニーズを発信するだけで売り手を集客 ・仲介業者を介さずにダイレクトにやり取り可能 ・潜在層にもリーチが可能 手数料無料 ※プラットフォーム案件の場合 
 ※
 売り手 1.掲載する ・買い手のM&Aニーズを自ら調べることが可能 ・仲介業者を介さずにダイレクトにやり取り可能 ・買い手のM&A担当者に直接コンタクトをとれる ・仲介業者を使わないので手数料が無料 2.オファーする M&A・出資ニーズを掲載 買い手のメリット 売り手のメリット ・仲介業者を使わないので手数料が無料 
 求人広告サイトのようなM&Aダイレクトマッチング 〇〇領域の会社を 募集します この会社と一緒に やっていきたい! 4 PR

Slide 5

Slide 5 text

Copyright © M&A Cloud All rights reserved. 注意事項 注意事項 ● すべてをリプレイスした、という話ではないです。 ○ 現在進行系です。 ● また、一部は意図して移行しません。これは後ほど説明します。 ● どちらのフレームワークが優れているかという話ではありませ ん。

Slide 6

Slide 6 text

Copyright © M&A Cloud All rights reserved. 移行経緯

Slide 7

Slide 7 text

Copyright © M&A Cloud All rights reserved. 既存のアプリケーション 既存のアプリケーション ● 2018年から開発が開始したLaravelによるモノリシックアプリ ケーション ● フロントエンドはBlade + Vue.js + PureJS(VanillaJS) / jQuery ○ Laravel標準のバリデーションやセッションフラッシュなど によるバリデーションエラー表示

Slide 8

Slide 8 text

Copyright © M&A Cloud All rights reserved. アプリケーションやビジネスの拡大に伴う要求の変化 アプリケーションやビジネスの拡大に伴う 要求の変化 ● UIをインタラクティブに変化させたい ○ 画面側に状態を持つ必要がある

Slide 9

Slide 9 text

Copyright © M&A Cloud All rights reserved. 既存アプリケーションでのVue.js 既存アプリケーションでのVue.js ● Vuex(ステート管理ライブラリ)は使っていない ○ 親子コンポーネント間でprops/emitでバケツリレー ● 一部Vue.js v2.6から追加されたVueObservable APIを利用して共 有ストアを作って状態管理などを行った ● 画面の初期データをBladeとVue.jsでの共有が辛い ○ スクリプトタグにJsonを出力するなどしてハイドレーション したりdata属性に出力

Slide 10

Slide 10 text

Copyright © M&A Cloud All rights reserved. Child.vue

Slide 11

Slide 11 text

Copyright © M&A Cloud All rights reserved. Parent.vue

Slide 12

Slide 12 text

Copyright © M&A Cloud All rights reserved.

Slide 13

Slide 13 text

Copyright © M&A Cloud All rights reserved. 複雑なUIの状態と戦う 複雑なUIの状態と戦う ● UIの管理が複雑化してきた ● 共通化できてないコンポーネント ○ 都度生み出される類似のボタンなど ● 既存仕様のまま戦うか、やり方を変えるか、

Slide 14

Slide 14 text

Copyright © M&A Cloud All rights reserved. UIを切り離す UIを切り離す ● Laravelで開発する場合、基本的にはBlade + JavaScript ● コンポーネントを共通化したいが、BladeとJavaScriptでの二重 管理になる可能性がある ○ LaravelからUIを完全に分離する

Slide 15

Slide 15 text

Copyright © M&A Cloud All rights reserved. フロントエンドをNuxt.jsに置き換える

Slide 16

Slide 16 text

Copyright © M&A Cloud All rights reserved. Nuxt.jsの選定 Nuxt.jsの選定 ● メンバー全員がVue.jsの経験あり ○ コンポーネントのライフサイクルにある程度の知見があった ● 個人的に何度か利用したことがあったので開発の初速が見込めた ● Next.js(React)でも良かったがVue.jsベースなので他メンバーの 学習コストも下げられて説得しやすかった ○ TypeScriptやCompositionAPIを導入したので学習コストは 若干あった

Slide 17

Slide 17 text

Copyright © M&A Cloud All rights reserved. Nuxt.jsとは Nuxt.jsとは Nuxt.jsはVue.jsを利用してユニバーサルアプリケーションを作成でき るオープンソースフレームワークです。 サーバーサイドレンダリング・静的ファイル生成・シングルページア プリケーションをサポートしています。 Vue.jsのプラグインであるVuexやVue Router、Vue Metaなどを内包 し、フルスタックなアプリケーション作成をサポート

Slide 18

Slide 18 text

Copyright © M&A Cloud All rights reserved. ユニバーサルモード ユニバーサルモード Nuxt.jsにはユニバーサルモードと呼ばれるアプリケーション状態があ ります。 これはHTTPリクエスト時の初期状態をSSRで表示し、以降のページ遷 移をSPA(CSR)として振る舞うハイブリッドで動作するアプリケーショ ンです。 SPAの課題であるSEOに対しても有効な手段です。

Slide 19

Slide 19 text

Copyright © M&A Cloud All rights reserved. フロントエンドとバックエンド フロントエンドとバックエンド ● フロントエンドにNuxt.jsを採用 ● バックエンドをそのままLaravlを使う ○ HTTP APIとして動作 ○ すでに存在するドメインオブジェクトは流用活用

Slide 20

Slide 20 text

Copyright © M&A Cloud All rights reserved. Open API(Swagger) Open API(Swagger) ● HTTP APIの定義はOpen APIを利用 L5-Swagger(swagger-php)を利用してController(弊社ではADRを採 用しているのでActionとResponder)にアノテーションを記述するこ とで定義書を管理 link: https://github.com/DarkaOnLine/L5-Swagger

Slide 21

Slide 21 text

Copyright © M&A Cloud All rights reserved.

Slide 22

Slide 22 text

Copyright © M&A Cloud All rights reserved. ADR(Action-Domain-Responder) ADR(Action-Domain-Responder) Paul M. Jones氏が提唱するMVC(Model-View-Controller)の改良型 アーキテクチャ (ざっくり) Model => Domain View => Responder Controller => Action link: https://en.wikipedia.org/wiki/Action–domain–responder

Slide 23

Slide 23 text

Copyright © M&A Cloud All rights reserved. ADRとOpen API ADRとOpen API ADRの最大の特徴は1つのエンドポイントに1つのAction(Class)にな ることが挙げられる。 この特徴を利用することで、Open APIのアノテーションをActionと そのActionが返却するResponderに集約されることで見通しよく記述 できる。

Slide 24

Slide 24 text

Copyright © M&A Cloud All rights reserved. Action

Slide 25

Slide 25 text

Copyright © M&A Cloud All rights reserved. Responder

Slide 26

Slide 26 text

Copyright © M&A Cloud All rights reserved. Responder

Slide 27

Slide 27 text

Copyright © M&A Cloud All rights reserved. Open APIのアノテーションが辛い Open APIのアノテーションが辛い ● 最初の導入こそ大変だが、利用する定義はどのエンドポイントも似 てくるので徐々に記述効率は良くなっている。 ● GitHub上でレビューする際にアノテーションで型のレビューなどが しやすい。 ● openapi-validatorを利用してAPI実装と定義が一致しているかをテ ストすることもでき、実装と定義書の乖離を防ぐことに役立った。 link: https://tech.macloud.jp/entry/2020/05/22/151820

Slide 28

Slide 28 text

Copyright © M&A Cloud All rights reserved. Nuxt.jsの実行環境

Slide 29

Slide 29 text

Copyright © M&A Cloud All rights reserved. AWS Lambda AWS Lambda AWS Lambdaはサーバーのプロビジョニングや管理の必要なしに、 コードが実行できる環境です。 Nuxt.jsのアプリケーションはこのAWS Lambda上で動作させます。 デプロイにはServerless Frameworkを利用して、静的ファイルやクラ イアントで実行されるJavaScriptファイルはS3に配置します。

Slide 30

Slide 30 text

Copyright © M&A Cloud All rights reserved. Serverless Framework Serverless Framework サーバーレスアプリケーションの構成管理やデプロイを行うツール プラグインが豊富でいろんなユースケースをカバーできる ● serverless-plugin-warmup ○ コールドスタート対策 ● serverless-prune-plugin ○ 古いバージョンを削除 ● serverless-cloudfront-invalidate ○ デプロイ後にCloudfrontのキャッシュを削除

Slide 31

Slide 31 text

Copyright © M&A Cloud All rights reserved.

Slide 32

Slide 32 text

Copyright © M&A Cloud All rights reserved. ● すべてのページを一括でNuxt.jsに移行するのは工数的に困難 ● 既存のLaraveはElasticBeanstalk上で稼働させている ● CloudfrontのBehaviorsを利用してパス毎にリクエストの流す先 を分岐させる ○ 段階的にNuxt.jsにリプレースされたページに移行していく 段階的なリリース 段階的なリリース

Slide 33

Slide 33 text

Copyright © M&A Cloud All rights reserved.

Slide 34

Slide 34 text

Copyright © M&A Cloud All rights reserved. 小ネタ:Lambda上のNuxt.jsからLaravelへのHTTPリクエストが通らない 小ネタ:Lambda上のNuxt.jsから LaravelへのHTTPリクエストが通らない ● Nuxt.jsからLaravelのHTTPのエンドポイントへのリクエストは axiosを利用 ○ LambdaにデプロイしたNuxt.js上でこのリクエストが失敗 (ステータスコード403) ○ どういうこと?

Slide 35

Slide 35 text

Copyright © M&A Cloud All rights reserved. 想定のリクエスト

Slide 36

Slide 36 text

Copyright © M&A Cloud All rights reserved. 実際のリクエスト

Slide 37

Slide 37 text

Copyright © M&A Cloud All rights reserved. だとしても何がイケないのか

Slide 38

Slide 38 text

Copyright © M&A Cloud All rights reserved. Cloudfrontは多段構成できない Cloudfrontは多段構成できない ● Cloudfrontは多段構成出来ない仕組みになっている ● Cloudfrontを経由したリクエストはヘッダーにviaというパラ メータが付与される ○ Lambda上で動かしているNuxt.jsで利用しているaxiosでは リクエストヘッダーを引き継いぐ ■ viaが引き継がれるので多段構成とみなされる Qiita: https://qiita.com/kubotak/items/fc1a877f99a569fc54bb

Slide 39

Slide 39 text

Copyright © M&A Cloud All rights reserved. ログインセッション

Slide 40

Slide 40 text

Copyright © M&A Cloud All rights reserved. ログインセッション ログインセッション ● LaravelとNuxt.jsが混在した状態でのログインセッションの共有 ○ Laravelで発行されるCookieをそのまま利用 ● クライアントで実行されるJSではaxiosによるリクエストに Cookieが付与される形でLaravel側でユーザーセッションが判断 できる ● サーバーサイドのNuxt.jsでも同様にHTTPリクエストから取得し たCookieをaxiosでリクエストに付与

Slide 41

Slide 41 text

Copyright © M&A Cloud All rights reserved. ユーザーを判別 SSR CSR with axios

Slide 42

Slide 42 text

Copyright © M&A Cloud All rights reserved. Cookieを付与するタイミング Cookieを付与するタイミング すべてのページをNuxt.jsで構築してしまうとサーバーがブラウザに Cookieを付与することができません。 ログインページや会員登録ページのPOST先などはLaravelで作られ たエンドポイントにリクエストさせて、ブラウザにログインセッショ ンのCookieを付与する設計になった

Slide 43

Slide 43 text

Copyright © M&A Cloud All rights reserved. POST Cookie付与

Slide 44

Slide 44 text

Copyright © M&A Cloud All rights reserved. リクエストバリデーション リクエストバリデーション Cookieを付与しなくてはいけないログインページや会員登録ページで はクライアントのみでバリデーションが完結しません。 [email protected] ************ 送信 placeholder 送信 invalid! ❓

Slide 45

Slide 45 text

Copyright © M&A Cloud All rights reserved. リクエストバリデーション リクエストバリデーション POST先でリクエストバリデーションを行った結果を元のページにエ ラーとして通知するためにエラー用のCookieを付与してクライアン ト側で表示させる [email protected] ************ 送信 placeholder 送信 invalid! 入力に誤りがあります

Slide 46

Slide 46 text

Copyright © M&A Cloud All rights reserved. 移行してどうだったか

Slide 47

Slide 47 text

Copyright © M&A Cloud All rights reserved. 動的に遷移するページを作れた 動的に遷移するページを作れた

Slide 48

Slide 48 text

Copyright © M&A Cloud All rights reserved. 移行後 移行後 ● TypeScriptによる型の恩恵 ● 旧環境ではVue.jsのコンポーネントとPureJSが混在していてUIが どちらの処理かわかりにくかった点などはすべてNuxt.jsに集約さ れた ● scoped CSSにより安全にCSSを書くことができるようになった ● アトミックデザインのようなコンポーネント設計を取り入れたので パーツの再利用性が上がり、サイトのテイストが統一された ● etc

Slide 49

Slide 49 text

Copyright © M&A Cloud All rights reserved. メンバーの声 メンバーの声 いいかんじ(≧∇≦)b 考えることが増えたので複雑になった 気がしますが、apiを適切に切ってれ ばこれ以上無闇に複雑化しないかもと いう期待はある。

Slide 50

Slide 50 text

Copyright © M&A Cloud All rights reserved. まとめ まとめ ● APIドキュメントが整備されているとフロントエンドとの連携がス ムーズ ● Lambdaを利用することでサーバーメンテナンスのコストをなくす ● CloudfrontのBehaviorsを利用して段階的に移行 ● LaravelのCookieはそのまま利用 ● LaravelとNuxt.jsでステートを共有するためにCookieを使う

Slide 51

Slide 51 text

Copyright © M&A Cloud All rights reserved. WE ARE HIRING! M&Aクラウドでは 一緒に働く仲間を募集しています PR https://www.wantedly.com/companies/macloud

Slide 52

Slide 52 text

Copyright © M&A Cloud All rights reserved. Thank you for watching :)