🙆

管理画面作り

2023/12/21に公開

社内のCMS開発経験に基づいた話

NextJSを用いてCMS開発の例として、参考になれば幸いです。(2023-8)

Rendering方式

SPA+CSR

@see NextでのCMS作り所感

ストア(State管理)

管理画面でのState管理は結構シンプルで、場合によって、

QueryClientのCacheをうまく使えば、State管理必須ではありません。

コードの可読性、メンテナンス性やState管理ライブラリの学習コストを配慮し、

適切に入れましょう。

使ったもの:

↑に保存したデータとして:

  • ログインしたユーザー情報
  • 通信エラー
  • 共通コンポーネントに関するデータ

それぞれの特徴

Context Reactive Variables Recoil
概要 Reactに内蔵、基本的な機能 GraphQLを導入する上に、Apollo Clientに内蔵、基本的な機能 外部StateManagementライブラリ、機能多様
メリット すぐ使える、ライブラリ不要 学習コスト低い、ApolloClientがProviderになり、APIの通信データとの連携しやすい。(自由に操るStateキャッシュというイメージ) 特化したState管理の外部ライブラリなので、豊かな機能を持ち、関心分離しや、Store管理しやすい
デメリット 実質Propsの渡しと同じく、不要なRenderingが発生する ApolloClientに依存するものの、可読性としてよろしくない。仕様によるQueryClinetの切り替えが困難 機能が多い一方、学習コスト高い
個人なり結論 ログインユーザー情報など、データの更新によって、ほぼ全てのコンテンツに影響渡すものに使用 Apollo導入前提でちょっとしたデータの管理にふさわしい、わざわざライブラリ導入までしなくても済む 複雑なState管理向け、特にComponentの裏側でのデータフローとロジックが重い場合

入力(フォーム)

管理画面でのデータ送信として、99%はフォーム経由で送信しているので、結構大事なパーツです。Formライブラリを入れることで、全局のStateと別にForm内に限ったState管理ができ、且つバリデーションの制定がしやすくなります。それに、簡単なUIを持ち、user interactionsができるFormライブラリも存在します。

使ったFormライブラリ:

  • Formik
  • React Hook Form

比較表:

Formik React Hook Form
Gzipped bundle size 44.34KB 12.12KB
Dependencies 7 0
GitHub stars 31.6k 32.2k
Active maintenance No Yes
Performance Good Good
Documentation Good Good
License Apache License version 2.0 MIT
NPM weekly downloads 2.1 Million 2.7 Million
Pricing Free Free
Community support Good Good
Open GitHub issues 635 3
Closed GitHub issues 1497 3528

構造:

  • schema機構

    • 項目ごと作成
      • couponSchema userSchemaとか
      • APIの引数に合わせる VS 表示に合わせる
        • 前者:データ処理が楽になる
        • 後者:UI表示が楽になる
        • 今まで前者を選んでた
    • カスタマイズ属性であらゆることができる
    • 各入力項目(inputField)ごと
    {
      name: "client_name",     ***//APIと統一、送信時の引数名***
      inputType: "TextField",  *//描画するコンポネート*
      label: "クライアント名",     //画面上表示する名称
      required: "クライアント名は必須です",  //必須項目かどうか
      validates: (v) => v.length <= 50 || "文字数は50文字以内にしてください",  *//バリデールール*
    },
    
  • FormGenerator機構

    • 各Formタイプの間Input,Confirm,Complete,Errorの切り替え(Store利用)
    • 見た目(レーアウト)作り
    • Submitイベント渡し
    • Form初期値処理
    • Schemaに記載したInput Filed情報でFormを生成する
  • inputGenerator機構

    • 入力コンポネートmapping

入力Component:

  • 汎用コンポネート

    • 一般的なInput Field(Text、Number、CheckBox、Radio)
  • 特殊コンポネート

    • Schemaのある属性に基づく処理を行いたい
      • 表示・非表示
      • Remoteからのデータをプルダウンで表示
      • 汎用コンポネートのカスタマイズ化や結合
  • ⚠️コンポネート作りにあたって

    • 画像・フィイルアップロード

    accept="image/png, image/jpeg, image/jpg”

    • <input>のaccept属性はディフォルトファイル種類しか設定できないため、拡張子チェックはバリデーションとして入れたほうが良さそう

    • 同名ファイルの二度目アップロードは認識されないため、onClickにe.currentTarget.value = "" というクリア処理が必要。

    • API通信とState管理としてFileタイプは扱える

    • 日時入力

      • 開始日と終了日が一行表示する場合が多いため、開始日と終了日を**1つコンポネート(datePicker)**としてまとめて、上記のSchemaのInputTypeにおいて、開始日がdatePicker,終了日がInvisble(不可視)という扱いしている

通信(API)

GraphQL と  REST ツパターンありますが、cmsにおいて特にパーフォマンスの優先順位そんな高くではないので、どっちを選んでも構いません、BE /BFFのメンバーに任せます。

※(FEのみんなさん、絶対GraphQLでしょう!!!!)

主な特徴↓

GraphQL REST
一個のendpointで集約 endpointで機能分け
client駆動アーキテクチャ server駆動アーキテクチャ
type safe、typeドキュメント自動生成 なし

GraphQLパターン

ApolloClientを採用している

Apolloの特徴↓

メリット デメリット
究極のGraphql Client、多機能 小規模のPJなら、要らない機能が多く入れられて、パフォマンスが落ちる
アクティブなコミュニティ、利用者数多い 多機能の一方、複雑な仕組みになり、学習コスト
Local State管理(Cache+Reactive Var) RESTAPIの対応もできるが機能はGraphqlより限られている

RESTパターン

あらゆるqueryClient(ex ReactQuery or SWR) +Axios

query clientはCache機能やAPIの全般管理+エラーハンドリングを提供してくれる

エラーハンドリング

queryClient(or apolloClient)のAPIで全てのAPI通信エラーを監視し、処理を行う。

特別な処理が必要な場合、各コンポネート内で、エラーを受け取って処理する。

認証

上記のcmsは全てAzureAD利用したSAML認証を採用しており、

Azure経由ログインできたユーザーを自前で作ったDBに入れて管理する。

ユーザー情報として、名前、メールとロールだけになります。

FEにおいての実装はかなりシンプルであり、下記の三つになります。

  1. ログイン

    下記の処理でログインする。

    青いURLはAzure側で設定する必要がある。

  2. ユーザー情報取得

    ログインができたとしても、FEとしてユーザーの情報が一切知らないので、

    ユーザー情報を取得するAPIを用意してもらう必要がある。

  3. ログインガード処理

    cmsに初アクセスする際にユーザー情報を取得しにいく

    • 取得できない場合(406:未認証)に、ログインページに遷移させる。

    or

    • ロール(権限)不足の場合、適切なページに遷移させる。

    その他に、

    ページに長い滞在することもあるので、ユーザー情報取得APIだけではなく、

    全てのAPIの認証エラーに対して、上記の青処理を行う。

    ※ HOC・Providerで処理を行っております。

⚠️注意点

認証エラーに対して、「エラーが起きたら処理する」ではなく、「ユーザー情報無事に取れたらページコンテンツを見せる」です

Discussion