RedwoodJSでTodoアプリを作ってみたので、所感をまとめてみる。

# 経緯
普段、僕はフロントエンドエンジニアとして業務を行なっているのですが、その時の雑談で「<strong>RedwoodJS</strong>」と呼ばれるフレームワークの存在を知り、実際に触ってみました。

ざっと目を通したところ、モダンなライブラリをこれでもかと詰め込んでおり、中々良さげなフレームワークでしたが、Qiitaで情報収集をしようとしたところ、なんと該当件数がたったの３件という状態でした。

![スクリーンショット 2022-08-13 19.20.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1692273/9b330107-ff9a-a626-4755-322e5f471e4e.png)

そこで今回、自分が実際にRedwoodJSを触って感じた所感をアウトプットすることで、Qiitaに存在するRedwoodJSの情報を少しでも増やせればいいな、RedwoodJSの認知度が僅かにでも上がればいいな、という思いでこの記事を書いてます。

説明が不足していたり、重要な箇所を書き逃しているかもしれませんが、
> 「RedwoodJSってこんな機能もあるんやで！」
そこの説明、ちょっと違うんじゃない？

といった点がありましたら、ぜひコメントにてご指摘くださいませ。

# 今回作ったTodoアプリ

今回作ったTodoアプリです。
リポジトリ：https://github.com/kirby0113/Redwood-todo
デプロイ先：https://redwood-todo.vercel.app/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1692273/bb267d5c-7e0b-37c0-f343-eef12972e59f.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1692273/0ddf6fa7-db05-75e9-d108-9388be80c569.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1692273/72dac9ea-38e2-b420-c62c-45abd28c5fdc.png)

![スクリーンショット 2022-08-13 23.26.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1692273/cf539784-1ad0-4891-d458-4d61932d29bd.png)

まだ未完成ではありますが、よかったら触ってみてください。

それでは、RedwoodJSの紹介をしていきます。

# RedwoodJSとは？
公式ドキュメント：https://redwoodjs.com/
Githubリポジトリ：https://github.com/redwoodjs/redwood
Star数：14,559 (2022年8月13日時点)

>Redwood is the full-stack web framework designed to help you grow from side project to startup.

<strong>RedwoodJS</strong>は、<strong>Webアプリケーションをより簡単に構築できる、尚且つ成長したWebアプリケーションが迅速に移行できること</strong>を目的としたフルスタックフレームワークです。
昨今のWeb開発でよく用いられているライブラリがいくつか纏められており、RedwoodJSのみでも十分モダンなWebアプリケーションが作成可能な作りとなっています。

「Redwood」という名前の由来は、北カリフォルニアに群生する巨木の種類名「レッドウッド」から来ているみたいです。公式曰く、

>Redwoods are beautiful as saplings, and grow to be majestic. What if you could feel that way about your web app?

レッドウッドのように<strong>雄大に成長するWebアプリを。</strong>

>Redwood pinecones are dense and surprisingly small. Can we allow you to get more done with less code?

レッドウッドに生える高密度な松ぼっくりのように、<strong>より少ないコードで、より様々なことを。</strong>

>Redwood trees are resistant to fire. Surprisingly robust to disaster scenarios, just like a great web framework should be!

火に強いレッドウッドのように、<strong>堅牢で、災害に対して強いWebアプリケーションを。</strong>

>Redwoods appear complex from afar, but simple up close. Their branching structure provides order and allows for emergent complexity within a simple framework. Can a web framework do the same?

遠くで見ると複雑だが、近くで見ると単純に見えるレッドウッドのように、<strong>単純なフレームワークの中に、複雑で秩序を持った構造を。</strong>

といった点をビジョンとして、開発がなされているようです。


# 僕がRedwoodJSに感じた魅力
早速ですが、僕がRedwoodJSに感じた魅力を簡単にまとめておきます。僕がこのフレームワークに感じた魅力は以下の点です。
### 充実したライブラリ

> Our mission is to help more startups
explore more territory, more quickly.

と公式が謳っているように、<strong>迅速なWebアプリケーション構築を可能にするために必要なライブラリが一通り揃っている</strong>印象でした。

技術選定をする間も無く、

>公式:「このライブラリを使うんだぞ！」

という風にされているのは、人によってはあまり気分の良いものではないかもしれませんが、個人的には楽でよかったです。

### チュートリアルが分かりやすい

[RedwoodJS公式チュートリアル](https://redwoodjs.com/docs/tutorial/foreword)

ドキュメントだけでなくチュートリアルも用意されており、一つのWebアプリケーションを実際に構築する流れが纏められています。RedwoodJSが初めてのWebアプリケーション開発だ、という人もお手軽に扱えそうです。

### CLIでお手軽実装

後述しますが、他フレームワークだと割と面倒な部分が、RedwoodJSから提供されるCLIのコマンドで速攻実装できるのがかなり魅力的でした。例えば、

- GraphQLのQuery・Mutation・Resolver定義
- 認証の実装

といった点は、提供されたコマンドで基本的な実装を全て行ってくれました。めちゃくちゃ良き。

### コアな技術が僕好みだった

（超個人的ですみません）

RedwoodJSは、「<strong>React</strong>」,「<strong>GraphQL</strong>」,「<strong>Prisma</strong>」がコアな技術として構築されています。これらについても後ほど触れますが、僕はこれらのライブラリが割と好きな方で、RedwoodJSにもすんなり入っていけました。（特にReactとPrismaにはお世話になっております）

この３つのライブラリは比較的知名度も高く、触ったことがある人は割と多いのではないでしょうか。そういった方であれば、RedwoodJSは簡単に使いこなせるかも。

逆に、
> 「俺はReactよりVue派なんだよーーー！！！」

とか、

> 「GraphQLよりはRESTっしょ〜〜〜」

って方には、あまりオススメできないかもしれません。

<strong>RedwoodJSは、フロント側はReact、サーバー側はPrisma、その架け橋としてGraphQLを用いる形になります。</strong>この辺りは公式の思想も滲み出てるかもしれませんね。
おそらくこの部分を変えることはできない、推奨されていないと思われます。

# RedwoodJSが提供するライブラリ
簡単にですが、RedwoodJSが主に提供しているライブラリを紹介しておきます。

### 共通部分

#### TypeScript

[TypeScript公式サイト](https://www.typescriptlang.org/)

- JavaScriptに型付けの機能を追加した言語
- TypeScriptを使うことで、実行時エラーを予防しながら開発が可能
- 自分はもう生のJavaScriptが書けません（）

#### GraphQL

[GraphQL公式サイト](https://graphql.org/)

- API向けに作られたクエリ言語
- REST APIと比べ、型が付けられる・柔軟にデータ取得ができる・エンドポイントが１つで済む、という点がメリットとして挙げられる
- パフォーマンスについてはRESTの方が良いかも。

#### Jest

[Jest公式サイト](https://jestjs.io/ja/)

- JavaScriptのテスティングフレームワーク
- 高速、モッキングが簡単な点から、よく用いられる印象
- [Testing Library](https://testing-library.com/)とセットで使われることが多い

### フロントエンド

#### React

[React公式サイト](https://ja.reactjs.org/)

- 言わずと知れたUI構築のためのJavaScriptライブラリ
- react hooksと呼ばれる機能を提供し、状態変化に応じて必要な部分のみ変更を加えることで、インタラクティブなWebアプリが開発できる
- 大体 AngularやVueと比較されている印象

#### Apollo Client

[Apollo Client公式サイト](https://www.apollographql.com/docs/react/)

- JavaScript用の状態管理ライブラリ
- React向けに作られており、GraphQLを使って、データのフェッチとキャッシュを管理する
- 大体GraphQLのAPIからデータ取得する場合、これが使われている印象

#### React Hook Form

[React Hook Form公式サイト](https://react-hook-form.com/jp/)

- Reactのフォームバリデーション用ライブラリ
- 各フォーム要素の入力を、再レンダリングなしで管理できる。
- 提供されるカスタムフックを用いることで、用意にフォームのバリデーションを作成可能
- [yup](https://github.com/jquense/yup)にバリデーションを任せて使われることも多い印象

#### react-hot-toast

[react-hot-toast公式サイト](https://react-hot-toast.com/)


- React用に開発された通知用コンポーネントを提供するライブラリ
- 見た目や挙動も比較的リッチで、ユーザーの目に止まりやすい通知が簡単に実装可能

#### Storybook

[Storybook 公式サイト](https://storybook.js.org/)

- コンポーネント駆動開発のための、コンポーネント管理ライブラリ
- コンポーネントの状態をカタログのように管理して表示することで、再利用可能で堅牢なコンポーネント開発を可能にする
- フロントエンドでコンポーネント駆動開発を行う場合、大体これが使われている印象

### バックエンド

#### Prisma

[Prisma 公式サイト](https://www.prisma.io/)

- Node.jsとTypeScript向けのORM（Object Relation Mapping）
- スキーマを記述し、migrationすることで、PrismaClientからデータ操作のためのメソッドが提供される
- データの操作がめちゃくちゃ簡単で、オブジェクト指向で扱えるので、データベースに意識を向けなくて良い点が推しポイント。

以上のライブラリが、RedwoodJSからデフォルトで提供されます。

# RedwoodJSを使う上で覚えておきたいこと
ここからは、RedwoodJSの機能の中から、

>ぼく:「これは押さえときたいよね！」

と思った点を2点紹介しておきます。
といっても、RedwoodJS独自の機能などは多くないので、<strong>RedwoodJSにまとめられているライブラリが使いこなせるかどうか、の方が重要</strong>ではあると思っています。

### Redwood CLI

[公式ドキュメントページ](https://redwoodjs.com/docs/cli-commands)

Redwood CLIを使いこなすことで、迅速な開発が可能となります。特に「認証の整備」や「GraphQLの環境整備」は時間を取られがちですが、このフレームワークでは、CLIを使うことで素早く構築可能です。

自分が主に使っていたコマンドを紹介しておきます。（option等については、公式ドキュメントをご覧下さい。）

#### Redwoodアプリケーションの環境構築
```
yarn create redwood-app <project directory> [option]
```
開発環境用コマンドです。
RedwoodJSは、yarnでの環境構築がデフォみたいです。
optionを変えることで、使うyarnのバージョンを変えたりできます。

#### ローカル環境の起動
```
yarn redwood dev
```
ローカル環境起動用コマンドです。

#### デプロイ準備用コマンド
```
yarn redwood deploy <target>
```
デプロイ環境を整えるためのコマンドです。
デプロイ先は充実しており、vercelやnetlify、AWSなどに対応してます。

#### ファイル生成コマンド
```
yarn redwood generate <type>
```
ファイル生成コマンドです。めっちゃ重要です。
使わなくても開発は可能ですが、必要なファイルはこれで揃えてくれるので、基本的に使った方が良いと思います。
GraphQLのリゾルバなどもこれを使って生成するほか、ページやコンポーネントも生成可能です。詳しくは[こちら](https://redwoodjs.com/docs/cli-commands#generate-alias-g)をご覧下さい。

#### いくつかのライブラリを利用するためのコマンド
```
yarn redwood <コマンドやライブラリ名>
```
例えば、prismaのマイグレーションであれば、
```
yarn redwood prisma migrate dev
```
Storybookの起動であれば、
```
yarn redwood storybook
```
といったようにコマンドを打つ必要があります。
この部分はちょっと慣れにくいポイントでした。。

#### 認証部分の生成コマンド
```
yarn redwood setup auth <provider>
```
認証部分の生成用コマンドです。これ１発でフロント側の認証用ページ、バックエンド側の認証機能を実装してくれます。
<strong>場合によって、幾つかカスタマイズが必要</strong>になりますが、基本的に公式ドキュメントを見ておけば問題ないと思います。詳しくは[こちら](https://redwoodjs.com/docs/authentication)をご覧下さい。

他にもコマンドは存在しますが、僕が今回の開発で主に使ったコマンドは以上です。

### ルーティングの実装

RedwoodJSでは、ルーティングを`web/src/Routes.tsx`に記述します。
今回のTodoアプリでは、以下のように記述しました。
```typescript:Routes.tsx
import { Router, Route, Set, Private } from '@redwoodjs/router'

import StandardLayout from './layouts/StandardLayout'
import TodoLayout from './layouts/TodoLayout'
import CreateTag from './pages/CreateTag'
import CreateTask from './pages/CreateTask'
import ForgotPasswordPage from './pages/ForgotPasswordPage/ForgotPasswordPage'
import LoginPage from './pages/LoginPage/LoginPage'
import ResetPasswordPage from './pages/ResetPasswordPage/ResetPasswordPage'
import SignupPage from './pages/SignupPage/SignupPage'
import TaskDetail from './pages/TaskDetail'
import Tasks from './pages/Tasks'

const Routes = () => {
  return (
    <Router>
      <Set>
        <Route path="/login" page={LoginPage} name="login" />
        <Route path="/signup" page={SignupPage} name="signup" />
        <Route path="/forgot-password" page={ForgotPasswordPage} name="forgotPassword" />
        <Route path="/reset-password" page={ResetPasswordPage} name="resetPassword" />
        <Route notfound page={NotFoundPage} />
      </Set>
      <Private unauthenticated="login">
        <Set wrap={[TodoLayout]}>
          <Route path="/" page={Tasks} name="tasks" />
        </Set>
        <Set wrap={[StandardLayout]}>
          <Route path="/task/create" page={CreateTask} name="createTask" />
          <Route path="/tag/create" page={CreateTag} name="createTag" />
          <Route path="/task/{id:Int}" page={TaskDetail} name="taskDetail" />
        </Set>
      </Private>
    </Router>
  )
}

export default Routes
```

ここから、少し分解していきます。

#### Route
```typescript:Routeコンポーネント
<Route path="/task/{id:Int}" page={TaskDetail} name="taskDetail" />
```
各ページへのルーティングを定義します。
- path: アクセスに要求するURL
- page: アクセスした際に表示するページコンポーネント
- name: routesオブジェクトからアクセスする際のメソッド名

routesオブジェクトについては、後ほど説明します。

#### Set

```typescript:Setコンポーネント
<Set wrap={[StandardLayout]}>
  <Route path="/task/create" page={CreateTask} name="createTask" />
  <Route path="/tag/create" page={CreateTag} name="createTag" />
  <Route path="/task/{id:Int}" page={TaskDetail} name="taskDetail" />
</Set>
```
Layoutコンポーネントを各ページにwrapするために使います。
Layoutコンポーネントについては、[こちら](https://redwoodjs.com/docs/tutorial/chapter1/layouts)をご覧下さい。（感覚的には、Laravelのテンプレートエンジンと同じ感じです。）

#### Private

```typescript:Privateコンポーネント
<Private unauthenticated="login">
  <Set wrap={[TodoLayout]}>
    <Route path="/" page={Tasks} name="tasks" />
  </Set>
  <Set wrap={[StandardLayout]}>
    <Route path="/task/create" page={CreateTask} name="createTask" />
    <Route path="/tag/create" page={CreateTag} name="createTag" />
    <Route path="/task/{id:Int}" page={TaskDetail} name="taskDetail" />
  </Set>
</Private>
```
公開範囲を指定できます。Privateにwrapされたルーティングは、認証されているユーザー以外は閲覧できず、`unauthenticated`に指定されたルーティングにリダイレクトされます。

#### routesオブジェクトについて
URLベースのルーティングの他に、RedwoodJSからはroutesオブジェクトが提供され、それを利用することで意図的にページ遷移させることができます。

例えば、Routesコンポーネントで
```typescript
<Route path="/task/{id:Int}" page={TaskDetail} name="taskDetail" />
```
と定義すると、
```typescript
routes.taskDetail()
```
が使えるようになり、柔軟にページ遷移を行うことが可能となります。
routesの利用の際には、基本的にRedwoodJS側から提供される他のコンポーネントと組み合わせて使うことになります。
詳細な利用法については、[こちら](https://redwoodjs.com/docs/router#named-route-functions-with-parameters)をご覧下さい。

とりあえずこの2点を押さえれば開発に支障はなさそうな印象ですが、
今後RedwoodJSへの知見が増え、

> ぼく：「「これめっちゃ重要じゃん！」

という部分が増えましたら、都度書き足していきます。

# 僕が感じたGoodとNext
ここまでを踏まえつつ、僕が開発中に感じたGoodな点と、Nextな点をまとめてみます。

### Goodな点

#### ライブラリ選定が楽・必要ない
僕はまだフロントエンドエンジニアとしての経験も短く、ライブラリの選定やライブラリを使うための環境整備に時間がかかりがちです。
RedwoodJSでは、そういった手間を大幅に削減してくれ、開発作業に専念することができました。
ただ、この部分は人によって好みが分かれそうです。

#### 認証による公開範囲の設定が簡単
他のフルスタックフレームワークを利用したことがないので比較はできていませんが、RedwoodJSは認証による公開範囲の設定が`<Private>`コンポーネントでwrapするのみでOKなので、非常に簡単な印象でした。

#### 認証の実装が簡単
認証に必要なページ・処理をコマンド１つで作成してくれる点は個人的に非常に助かりました。幾つかカスタマイズが必要な場合もありますが、それを踏まえても、他フレームワーク・ライブラリと比べてかなり手軽に実装可能でした。

#### Prismaのスキーマとコマンド１つで、GraphQLの実装に必要なリゾルバなどを１発で揃えてくれる
GraphQLの実装の際、リゾルバやクエリの定義には時間を取られがちですが、RedwoodJSでは、基本的なものについてはコマンド１つで全て揃えてくれます。

#### Good総括

- <strong>面倒な部分をとにかく簡単に実装可能にしてくれる。</strong>
- <strong>他ライブラリの機能を活かしつつ、迅速なアプリ開発を行うための機能に力を入れられている印象だった。</strong>
- <strong>あらかじめ技術が選定されている点は、人を選ぶかも。</strong>

### Next

#### RedwoodJSのオリジナル機能はほぼなさそうだった

僕が見逃している可能性もありますが、RedwoodJSが他ライブラリにないような機能を実装しているようなことはほぼなさそうでした。
RedwoodJSは良くも悪くも<strong>「ライブラリの集合体」で、「既存の開発をスムーズに行うためのもの」</strong>と考えておくのが良さそうです。
とはいえ、RedwoodJSの目的である「<strong>Webアプリケーションをより簡単に構築できる、尚且つ成長したWebアプリケーションが迅速に移行できる</strong>」については、十分達成されていると思います。

#### いくつか機能しないライブラリが存在する可能性がある

通知の実装のために、「[react-toastify](https://github.com/fkhadra/react-toastify)」を使おうとしたのですが、RedwoodJSではうまく機能しませんでした。
今回はRedwoodJSから別ライブラリが提供されていたので一旦OKでしたが、どうしても使いたいライブラリを使えない場合が存在するかもしれません。

#### コアな技術の好き嫌いがそのままRedwoodJSの好き嫌いにつながる
コアな技術に「React」,「GraphQL」,「Prisma」が使われることは先述しましたが、これらのライブラリが好みでないような人にとって、RedwoodJSはあまり好みでないフレームワークになると思います。

#### 自動生成されたリゾルバの中に、パフォーマンス上望ましくないものが存在する場合がある
RedwoodJSが提供するCLIを使うことで、自動的にGraphQLに必要なファイルを自動生成してくれる点については紹介したかと思いますが、ここで生成されるファイルの中に、パフォーマンス上よろしくないコードが存在することがありました。

例えば、以下のようなスキーマを定義し、GraphQLのリゾルバを生成したとします。
```:schema.prisma
model Task {
  id          Int      @id @default(autoincrement())
  name        String
  detail      String
  priority    Int
  tags        Tag[]
  is_checked  Boolean
  is_archived Boolean
  created_at  DateTime @default(now())
  user        User     @relation(fields: [user_id], references: [id])
  user_id     Int
}
```
この際に、RedwoodJSは以下のようなリゾルバを生成します。
```typescript:tasks.ts
export const Task: TaskResolvers = {
  tags: (_obj, { root }) =>
    db.task.findUnique({ where: { id: root.id } }).tags(),
}
```
このリゾルバが存在すると、タスクのデータを取得した際に、relationで繋がっているタグのデータを同時に取得してくれます。

一見便利そうに見えますが、これでは<strong>タスクの取得と、それに繋がっているタグの取得が別のクエリとなってしまいます。</strong>

この点については、このリゾルバは手作業で削除し、タスク取得の部分で以下のように、同時にタグを取得するように実装することが望ましいと思います。
```typescript
  return db.task.findUnique({
    where: { id },
    include: { tags: true },
  })
```

#### Next総括
- <strong>オリジナルの機能はなさそう。</strong>
- <strong>使えないライブラリが存在する？</strong>
- <strong>手作業でのカスタマイズは必要になりそう。</strong>
- <strong>ライブラリ面での自由度は低い</strong>

# RedwoodJSはどう使っていくべきか
RedwoodJSが提供する機能は非常に便利なものであり、迅速な開発の手助けとなっていることは間違いないと僕は思っています。
ただ、その機能で作ったファイルが理想的なものかと言われると、それはまた違う話になります。

プロジェクトに求められる機能や基盤は、提供された機能を活用して迅速に整え、<strong>必要に応じて、パフォーマンスの向上・コードのリファクタリング等を行うようにした方が良さそうです。</strong>

# おわりに
RedwoodJS、個人的にはとても好みなフレームワークでした。
JavaScriptを使われている方で、フルスタックフレームワークを利用した開発がしたい、という方にはうってつけだと思います！

この記事を読んで

> 「RedwoodJS面白そうやんけ！」

と感じた方！
プロジェクト構築も簡単ですから、ぜひ触ってみてください！
そして、ぜひQiitaやZennに知見をアウトプットしてください（願望）

以上です〜。

# 参考資料
- [RedwoodJS公式ドキュメント](https://redwoodjs.com/docs/introduction)
- [フルスタックWebフレームワーク「RedwoodJS」のチュートリアルをやってみた](https://zenn.dev/rinda_1994/articles/9d4af758ea4980)