PHP Conference 2020 Track4
Copyright © M&A Cloud All rights reserved.Laravelで運用しているサービスをNuxt.jsにリプレイスするPHP Conference 2020/Track 4Kenjiro Kubota
View Slide
Copyright © M&A Cloud All rights reserved.Profile2久保田 賢二朗kubotak-iskubotak_publickenjiro.kubota株式会社M&AクラウドJavaScript GoPHPhttps://kubotak.page
Copyright © M&A Cloud All rights reserved.PR
Copyright © M&A Cloud All rights reserved.買い手 ・案件報酬はM&A成功報酬のみ・最低手数料なし・売り手ソーシングのチャネルが増える・M&Aニーズを発信するだけで売り手を集客・仲介業者を介さずにダイレクトにやり取り可能・潜在層にもリーチが可能手数料無料※プラットフォーム案件の場合 ※ 売り手1.掲載する・買い手のM&Aニーズを自ら調べることが可能・仲介業者を介さずにダイレクトにやり取り可能・買い手のM&A担当者に直接コンタクトをとれる・仲介業者を使わないので手数料が無料2.オファーするM&A・出資ニーズを掲載買い手のメリット 売り手のメリット・仲介業者を使わないので手数料が無料 求人広告サイトのようなM&Aダイレクトマッチング〇〇領域の会社を募集しますこの会社と一緒にやっていきたい!4PR
Copyright © M&A Cloud All rights reserved.注意事項注意事項● すべてをリプレイスした、という話ではないです。○ 現在進行系です。● また、一部は意図して移行しません。これは後ほど説明します。● どちらのフレームワークが優れているかという話ではありません。
Copyright © M&A Cloud All rights reserved.移行経緯
Copyright © M&A Cloud All rights reserved.既存のアプリケーション既存のアプリケーション● 2018年から開発が開始したLaravelによるモノリシックアプリケーション● フロントエンドはBlade + Vue.js + PureJS(VanillaJS) / jQuery○ Laravel標準のバリデーションやセッションフラッシュなどによるバリデーションエラー表示
Copyright © M&A Cloud All rights reserved.アプリケーションやビジネスの拡大に伴う要求の変化アプリケーションやビジネスの拡大に伴う要求の変化● UIをインタラクティブに変化させたい○ 画面側に状態を持つ必要がある
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属性に出力
Copyright © M&A Cloud All rights reserved.Child.vue
Copyright © M&A Cloud All rights reserved.Parent.vue
Copyright © M&A Cloud All rights reserved.
Copyright © M&A Cloud All rights reserved.複雑なUIの状態と戦う複雑なUIの状態と戦う● UIの管理が複雑化してきた● 共通化できてないコンポーネント○ 都度生み出される類似のボタンなど● 既存仕様のまま戦うか、やり方を変えるか、
Copyright © M&A Cloud All rights reserved.UIを切り離すUIを切り離す● Laravelで開発する場合、基本的にはBlade + JavaScript● コンポーネントを共通化したいが、BladeとJavaScriptでの二重管理になる可能性がある○ LaravelからUIを完全に分離する
Copyright © M&A Cloud All rights reserved.フロントエンドをNuxt.jsに置き換える
Copyright © M&A Cloud All rights reserved.Nuxt.jsの選定Nuxt.jsの選定● メンバー全員がVue.jsの経験あり○ コンポーネントのライフサイクルにある程度の知見があった● 個人的に何度か利用したことがあったので開発の初速が見込めた● Next.js(React)でも良かったがVue.jsベースなので他メンバーの学習コストも下げられて説得しやすかった○ TypeScriptやCompositionAPIを導入したので学習コストは若干あった
Copyright © M&A Cloud All rights reserved.Nuxt.jsとはNuxt.jsとはNuxt.jsはVue.jsを利用してユニバーサルアプリケーションを作成できるオープンソースフレームワークです。サーバーサイドレンダリング・静的ファイル生成・シングルページアプリケーションをサポートしています。Vue.jsのプラグインであるVuexやVue Router、Vue Metaなどを内包し、フルスタックなアプリケーション作成をサポート
Copyright © M&A Cloud All rights reserved.ユニバーサルモードユニバーサルモードNuxt.jsにはユニバーサルモードと呼ばれるアプリケーション状態があります。これはHTTPリクエスト時の初期状態をSSRで表示し、以降のページ遷移をSPA(CSR)として振る舞うハイブリッドで動作するアプリケーションです。SPAの課題であるSEOに対しても有効な手段です。
Copyright © M&A Cloud All rights reserved.フロントエンドとバックエンドフロントエンドとバックエンド● フロントエンドにNuxt.jsを採用● バックエンドをそのままLaravlを使う○ HTTP APIとして動作○ すでに存在するドメインオブジェクトは流用活用
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
Copyright © M&A Cloud All rights reserved.ADR(Action-Domain-Responder)ADR(Action-Domain-Responder)Paul M. Jones氏が提唱するMVC(Model-View-Controller)の改良型アーキテクチャ(ざっくり)Model => DomainView => ResponderController => Actionlink: https://en.wikipedia.org/wiki/Action–domain–responder
Copyright © M&A Cloud All rights reserved.ADRとOpen APIADRとOpen APIADRの最大の特徴は1つのエンドポイントに1つのAction(Class)になることが挙げられる。この特徴を利用することで、Open APIのアノテーションをActionとそのActionが返却するResponderに集約されることで見通しよく記述できる。
Copyright © M&A Cloud All rights reserved.Action
Copyright © M&A Cloud All rights reserved.Responder
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
Copyright © M&A Cloud All rights reserved.Nuxt.jsの実行環境
Copyright © M&A Cloud All rights reserved.AWS LambdaAWS LambdaAWS Lambdaはサーバーのプロビジョニングや管理の必要なしに、コードが実行できる環境です。Nuxt.jsのアプリケーションはこのAWS Lambda上で動作させます。デプロイにはServerless Frameworkを利用して、静的ファイルやクライアントで実行されるJavaScriptファイルはS3に配置します。
Copyright © M&A Cloud All rights reserved.Serverless FrameworkServerless Frameworkサーバーレスアプリケーションの構成管理やデプロイを行うツールプラグインが豊富でいろんなユースケースをカバーできる● serverless-plugin-warmup○ コールドスタート対策● serverless-prune-plugin○ 古いバージョンを削除● serverless-cloudfront-invalidate○ デプロイ後にCloudfrontのキャッシュを削除
Copyright © M&A Cloud All rights reserved.● すべてのページを一括でNuxt.jsに移行するのは工数的に困難● 既存のLaraveはElasticBeanstalk上で稼働させている● CloudfrontのBehaviorsを利用してパス毎にリクエストの流す先を分岐させる○ 段階的にNuxt.jsにリプレースされたページに移行していく段階的なリリース段階的なリリース
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)○ どういうこと?
Copyright © M&A Cloud All rights reserved.想定のリクエスト
Copyright © M&A Cloud All rights reserved.実際のリクエスト
Copyright © M&A Cloud All rights reserved.だとしても何がイケないのか
Copyright © M&A Cloud All rights reserved.Cloudfrontは多段構成できないCloudfrontは多段構成できない● Cloudfrontは多段構成出来ない仕組みになっている● Cloudfrontを経由したリクエストはヘッダーにviaというパラメータが付与される○ Lambda上で動かしているNuxt.jsで利用しているaxiosではリクエストヘッダーを引き継いぐ■ viaが引き継がれるので多段構成とみなされるQiita: https://qiita.com/kubotak/items/fc1a877f99a569fc54bb
Copyright © M&A Cloud All rights reserved.ログインセッション
Copyright © M&A Cloud All rights reserved.ログインセッションログインセッション● LaravelとNuxt.jsが混在した状態でのログインセッションの共有○ Laravelで発行されるCookieをそのまま利用● クライアントで実行されるJSではaxiosによるリクエストにCookieが付与される形でLaravel側でユーザーセッションが判断できる● サーバーサイドのNuxt.jsでも同様にHTTPリクエストから取得したCookieをaxiosでリクエストに付与
Copyright © M&A Cloud All rights reserved.ユーザーを判別SSRCSRwith axios
Copyright © M&A Cloud All rights reserved.Cookieを付与するタイミングCookieを付与するタイミングすべてのページをNuxt.jsで構築してしまうとサーバーがブラウザにCookieを付与することができません。ログインページや会員登録ページのPOST先などはLaravelで作られたエンドポイントにリクエストさせて、ブラウザにログインセッションのCookieを付与する設計になった
Copyright © M&A Cloud All rights reserved.POSTCookie付与
Copyright © M&A Cloud All rights reserved.リクエストバリデーションリクエストバリデーションCookieを付与しなくてはいけないログインページや会員登録ページではクライアントのみでバリデーションが完結しません。[email protected]************送信placeholder送信invalid! ❓
Copyright © M&A Cloud All rights reserved.リクエストバリデーションリクエストバリデーションPOST先でリクエストバリデーションを行った結果を元のページにエラーとして通知するためにエラー用のCookieを付与してクライアント側で表示させる[email protected]************送信placeholder送信invalid!入力に誤りがあります
Copyright © M&A Cloud All rights reserved.移行してどうだったか
Copyright © M&A Cloud All rights reserved.動的に遷移するページを作れた動的に遷移するページを作れた
Copyright © M&A Cloud All rights reserved.移行後移行後● TypeScriptによる型の恩恵● 旧環境ではVue.jsのコンポーネントとPureJSが混在していてUIがどちらの処理かわかりにくかった点などはすべてNuxt.jsに集約された● scoped CSSにより安全にCSSを書くことができるようになった● アトミックデザインのようなコンポーネント設計を取り入れたのでパーツの再利用性が上がり、サイトのテイストが統一された● etc
Copyright © M&A Cloud All rights reserved.メンバーの声メンバーの声いいかんじ(≧∇≦)b 考えることが増えたので複雑になった気がしますが、apiを適切に切ってればこれ以上無闇に複雑化しないかもという期待はある。
Copyright © M&A Cloud All rights reserved.まとめまとめ● APIドキュメントが整備されているとフロントエンドとの連携がスムーズ● Lambdaを利用することでサーバーメンテナンスのコストをなくす● CloudfrontのBehaviorsを利用して段階的に移行● LaravelのCookieはそのまま利用● LaravelとNuxt.jsでステートを共有するためにCookieを使う
Copyright © M&A Cloud All rights reserved.WE ARE HIRING!M&Aクラウドでは一緒に働く仲間を募集していますPRhttps://www.wantedly.com/companies/macloud
Copyright © M&A Cloud All rights reserved.Thank you for watching :)