🕰️

Refineでつくる 5分で簡単 管理画面

2023/09/27に公開

はじめに

アプリ開発には本体の開発とは別に、運用・保守するための管理画面の開発も必要不可欠になると思います。機能と言っても、登録、参照、編集、削除 程度であることがほとんどなので、そこまで時間もかけたくないものです。そこで今回は、弊社で採用することにした Refine についてご紹介したいと思います。

https://refine.dev

多少の環境構築はあるものの、準備が整えば、1 ページあたり 5 分で実装できるようになります。

豊富なサンプル

GUI を使って

上記の公式サイトを見ると、「Try it Online!」のボタンがあります(2023-09 現在)。ここから要素技術を選択していくことで、お好みのプロジェクトが作成可能です。

GitHub から Clone

https://refine.dev/docs/examples/

この公式ページには、コンポーネント、フレームワーク、UI など様々な要件・要素技術に応じたサンプルコードが GitHub 上に数多く提供されています。

今回、弊社は App Router を採用したかったため、こちら をベースにしました。GUI や他のサンプルでは、まだ Page Router での実装なので、App Router を採用したい方は、この手順がよいと思います。( Page Router からの書き換えを試みましたが、時間がもったいないので断念しました。)

カスタマイズ

デフォルト

実際に、npm run dev などで起動するとわかりますが、ほとんど仕上がっている状態です。

  1. 認証認可
    1. refinedev/core
  2. UI ライブラリ
    1. refinedev/antd
  3. データアクセス
    1. refinedev/simple-rest

他にもいくつかの要素が refine ライブラリにより実装されています。プロジェクトに合わせて、カスタマイズすることで、ローコストで管理画面が作成可能です。

採用したアーキテクチャ

少々話が脱線しますが、以前、フロントエンド開発における仕様変更に強くするためノウハウ記事を書きました。
https://zenn.dev/ficilcom/articles/app_router_registant_to_changes

今回はあくまで内部向けの開発なので以下の理由から、上記は採用していません

  • 機能性が CRUD 程度に留まり、拡張の所要がない。
  • 仕様変更頻度が著しく少ない。テーブル追加は流れ作業で対応可能。
  • UI ライブラリの置き換え、バージョンアップを頻繁に行わない。
  • Refine Dev と ant-design の相性が良く、強力なコンポーネントが確立されている。

レビューの観点で、ファイルが分離されている方が見やすいといった効果があるので、そう言った可読性に関する技法は採用しています。

いくつかある中で、データアクセスについて今回は取り上げたいと思います。

データアクセス/DataProvider

https://refine.dev/docs/api-reference/core/providers/data-provider/#usage

このドキュメントにもあるように

import { DataProvider } from "@refinedev/core";

を実装することで、データアクセスを実現できるのですが、これにも数多くの DataProvider が提供されています。開発しているアプリの API Gateway に合わせた Provider を採択することで、ローコストな開発が可能です。以下は一例です。詳細はこちら

以下は、Hasura サンプルの一部ですが、これだけでデータアクセスが可能です。

src/pages/categories/list.tsx
import { IResourceComponentsProps } from "@refinedev/core";
import { List, useTable, EditButton, DateField, getDefaultSortOrder }
  from "@refinedev/antd";
import { Table } from "antd";
import { ICategory } from "../../interfaces";

export const CategoryList: React.FC<IResourceComponentsProps> = () => {
  const { tableProps, sorter } = useTable<ICategory>({
    initialSorter: [
      {
        field: "id",
        order: "asc",
      },
    ],
    metaData: {
      fields: ["id", "title", "created_at"],
    },
  });

  return (
    <List>
      <Table {...tableProps} rowKey="id">
      // 省略
      </Table>
    </List>
  );
};

useTable() に適切な引数を渡すことで以下の graphql query を発行することができます。mutation についても、同様で 適切な引数を渡すことで、CUD 操作が容易に実現できます。ここでは詳しく解説しませんが、DataProvider ごとに、引数の形式は異なるので、公式ドキュメントやソースコードを確認してください。

query (
  $limit: Int
  $offset: Int
  $order_by: [categories_order_by!]
  $where: categories_bool_exp
) {
  categories(
    limit: $limit
    offset: $offset
    order_by: $order_by
    where: $where
  ) {
    id
    title
    created_at
  }
  categories_aggregate(where: $where) {
    aggregate {
      count
    }
  }
}

フレームワークにより仕様が隠蔽されているため、学習コストがかかりますが、そこを乗り越えれば、あとは単純作業です。特に私が気に入っているのは、graphql schema を作成して、code-gen しなくて済むといった、少ない量のコードで実現できる点です。ファイルが増えたり、複雑なクエリを組む余地があるのは、レビューが負担になり、生産性の低下に繋がります。

おわりに

重要だが、単純な作業のみになる開発に直面することはあると思います。そう言ったものはすでにアプリ化されている可能性があり、知っているか知らないかにより生産性、開発体験に影響があるので、一度調べてみるのが良さそうです。

他にも、さまざまな Provider や Hooks が提供されているようなので、おすすめな知見あれば、共有していきたいと思います。

GitHubで編集を提案
フィシルコム

Discussion