Open13

frourio環境構築

shin_k_2281shin_k_2281

開発で必要になったfrourioのキャッチアップを目的に環境構築していく。
DockerでPostgreSQL環境を立てて、一旦ローカルで開発してみる。
ちょっと本番デプロイに関しては後回しにする。
ちなみにNext.js以外なにもわからない

shin_k_2281shin_k_2281

DockerでPostgreSQLサーバーを立てる

FROM postgres:14-alpine

ENV TZ Asia/Tokyo

ENV LANG ja_JP.UTF-8
ENV LANGUAGE ja_JP:ja
ENV LC_ALL ja_JP.UTF-8
version: '3'
services:
  db:
    build: .
    ports:
      - 5432:5432
    environment:
      POSTGRES_USER: admin
      POSTGRES_PASSWORD: admin
      POSTGRES_DB: frourio_demo_db

作っておいたディレクトリ内に上記2つを作成しdocker-compose upしておく
(ファイルはめちゃくちゃ他の人のをパクった)

shin_k_2281shin_k_2281

frourioコマンド実行

npx create-frourio-appをやって以下のように選択した

しばらくしたら終わったようで見てみたら

$ run-p generate:*
...
Starting: generate:aspida

Starting: generate:server
node:internal/modules/cjs/loader:936
  throw err;
  ^

一通り成功してそうな後に、run-p generate:*というコマンドを勝手に実行してて
勝手にエラーが出ていた、大丈夫だろうか

shin_k_2281shin_k_2281

現状のディレクトリ

frourio-demo-app
├── Dockerfile
├── docker-compose.yml
├── app
│   ├── README.md
│   ├── aspida.config.js
│   ├── components
│   ├── jest.config.ts
│   ├── next-env.d.ts
│   ├── node_modules
│   ├── package.json
│   ├── pages
│   ├── public
│   ├── server
│   ├── styles
│   ├── test
│   ├── tsconfig.json
│   ├── utils
│   └── yarn.lock
└── node_modules
shin_k_2281shin_k_2281
"scripts": {
    "dev": "npm run migrate:dev && run-p dev:*",
    "dev:client": "next dev -p 8001",
    "dev:server": "npm run dev --prefix server",
    "dev:aspida": "aspida --watch",

package.jsonが上のようになっていたのでlocalhost:8001に接続

shin_k_2281shin_k_2281

ディレクトリが気持ち悪いので、Dockerfiledocker-compose.ymlをまとめてしまう
なぜか外部にできたnode_modulesはよくわからないけど消しちゃう

frourio-demo-app
├── Dockerfile
├── README.md
├── aspida.config.js
├── components
├── docker-compose.yml
├── jest.config.ts
├── next-env.d.ts
├── node_modules
├── package.json
├── pages
├── public
├── server
├── styles
├── test
├── tsconfig.json
├── utils
└── yarn.lock
shin_k_2281shin_k_2281

scripts変更

npx prisma studioという便利なものがあるらしい
https://www.prisma.io/docs/concepts/components/prisma-studio

npm scriptsに以下を追加する(仲間に教えてもらった)

"dev:prisma": "cd ./server && npx prisma studio",

こうするとyarn devをした時にnpm run-allが動き、dev:*で登録されたscriptsが全部動くため、開発サーバーと共にprisma studioが立ち上がる

shin_k_2281shin_k_2281

chakraUIを入れる

スタイリングには主にchakraUIを使用していく

公式サイトより
https://chakra-ui.com/guides/getting-started/nextjs-guide

yarn add @chakra-ui/react @emotion/react@^11 @emotion/styled@^11 framer-motion@^4

_app.tsxを次のようにする

import '../styles/globals.css'

import { ChakraProvider } from '@chakra-ui/react'
import type { AppProps } from 'next/app'

const MyApp = ({ Component, pageProps }: AppProps) => {
  return (
    <ChakraProvider>
      <Component {...pageProps} />
    </ChakraProvider>
  )
}

export default MyApp

一旦がっつり作るものではないので
colorThemeとかglobalStylesとかは特に上書きせずに使おうかなと思う

shin_k_2281shin_k_2281

Recoilを入れる

状態管理はRecoilを使うとのことなので入れておく

recoilの概念についてはこちらにある図がわかりやすかった
https://blog.uhy.ooo/entry/2021-07-24/react-state-management/#アーキテクチャ上の特徴

公式サイトより
https://recoiljs.org/docs/introduction/installation

yarn add recoil

公式サイトをもとに_app.tsxを次のようにする
https://recoiljs.org/docs/introduction/getting-started

import '../styles/globals.css'

import { ChakraProvider } from '@chakra-ui/react'
import type { AppProps } from 'next/app'
import { RecoilRoot } from 'recoil'

const MyApp = ({ Component, pageProps }: AppProps) => {
  return (
    <ChakraProvider>
      <RecoilRoot>
        <Component {...pageProps} />
      </RecoilRoot>
    </ChakraProvider>
  )
}

export default MyApp

次のようなワードがよく出てきそう
atom,selector,useRecoilState,useRecoilValue

Recoilをためす

https://recoiljs.org/docs/basic-tutorial/intro
チュートリアルを見つつ、frourio初期状態のTODOに対して、フロント側でTODOを状態管理して他の子コンポーネントからTODO一覧が表示できるみたいな状態を目指す

https://qiita.com/tkmd35/items/b4630e53a907d96e3430
上を参考に次のファイルを追加した(そろそろフロント側をsrcにまとめたくなってきた)

recoil
┝ atom.ts
┝ selector.ts
└ key.ts

参考

https://qiita.com/tkmd35/items/b4630e53a907d96e3430

shin_k_2281shin_k_2281

schema.prismaの定義

datasource db {
  provider = "postgresql"
  url      = env("API_DATABASE_URL")
}

generator client {
  provider = "prisma-client-js"
}

model User {
  id         Int      @id @default(autoincrement())
  email      String   @unique
  name       String   @db.VarChar(128)
  imageURL   String?
  created_at DateTime @default(now()) @db.Timestamp(0)
  updated_at DateTime @default(now()) @updatedAt @db.Timestamp(0)
  topic      Topic[]
  answer     Answer[]
  like       Like[]
}

model Topic {
  id              Int      @id @default(autoincrement())
  userId          Int
  title           String   @db.VarChar(128)
  content         String   @db.Text
  limitAnswerChar Int
  answerClosedAt  DateTime
  close           Boolean
  created_at      DateTime @default(now()) @db.Timestamp(0)
  updated_at      DateTime @default(now()) @updatedAt @db.Timestamp(0)

  answer Answer[]
  user   User     @relation(fields: [userId], references: [id])
}

model Answer {
  id         Int      @id @default(autoincrement())
  topicId    Int
  userId     Int
  answer     String   @db.VarChar(64)
  created_at DateTime @default(now()) @db.Timestamp(0)
  updated_at DateTime @default(now()) @updatedAt @db.Timestamp(0)

  Like  Like[]
  topic Topic  @relation(fields: [topicId], references: [id])
  user  User   @relation(fields: [userId], references: [id])
}

model Like {
  answerId   Int
  userId     Int
  created_at DateTime @default(now()) @db.Timestamp(0)

  answer Answer @relation(fields: [answerId], references: [id])
  user   User   @relation(fields: [userId], references: [id])
  @@id([answerId, userId])
}

このようなものを作成してみた