ポートフォリオ作り: Pokemon app
前提
Udemyの教材
のNARUTO図鑑アプリをやって、その後、自分で似たようなアプリを作ってみる。ちなみに、NARUTO図鑑アプリの作ったのはこれ。
(create-react-appをViteに、CSSをUnoCSSに変更して作成。GitHub PagesへビルドするのはGitHub Actionsを使用)
技術スタック
今回は
- React, TypeScript, Vite
- React Router
- ゼロランタイムのCSS in JS(なんか熱いらしいので) Linaria
- できれば Chart.js とか数値をグラフ化するのをしたい(好奇心)
追記、StyleLintの勉強会聞いて、面白そうだから規約バリバリにしてみる。(Storybookは今回はデザイン適当だから今度からにする)
- Prettier
- ESLint
- StyleLint
CI / CD もやる
GitHub Actions
- コードチェッカー
- テスト
- GitHub Pagesへデプロイ
お約束の
- OGP設定
- SEOは検索避ける(練習用のポートフォリオでGoogleのポリシーに違反するため)
使用API
PokeAPI v2
作成ページ
- ポケモン 一覧 ページネーション、検索(インクリメンタルサーチ)もつけたい(好奇心)
- 1ポケモンの詳細画面
作成期間
予定: 2週間(4h * 4d = 16h)
デザイン
今回は作らない。適当にやる。
土台作り
プロジェクトの作成
参考: https://ja.vite.dev/guide/
$ npm create vite@latest pokemon-app -- --template react-ts
$ cd pokemon-app
React Routerのインストール
参考: https://reactrouter.com/en/main/start/tutorial
$ npm install react-router-dom
Linariaのインストール
参考: https://www.npmjs.com/package/linaria
$ npm i linaria
Chart.jsのインストール
参考: https://www.npmjs.com/package/chart.js?activeTab=readme
$ npm i chart.js
Prettier + ESLint + StyleLint のインストールと設定
Prettierのインストール
の通りにインストール
{
"trailingComma": "es5",
"tabWidth": 4,
"semi": false,
"singleQuote": true
}
ESLintとの連携
ESLintはViteに初期から設定されている
通りにインストールして、// (importの最後)
+ import eslintConfigPrettier from "eslint-config-prettier";
export default tseslint.config(
// (...略)
{
extends: [
js.configs.recommended,
...tseslint.configs.recommended,
+ eslintConfigPrettier,
],
// (...略)
を設定する。
StyleLintのインストールとPrettireとの連携
今回、ゼロランタイム CSS-in-JSの Linaria だから、
参考: https://stylelint.io/user-guide/get-started#linting-css-like-languages-and-css-within-containers, https://github.com/callstack/linaria/blob/master/docs/LINTING.md
npm install --save-dev stylelint @linaria/stylelint-config-standard-linaria stylelint-config-prettier
npm install --save-dev stylelint-processor-styled-components
touch .stylelintrc.json
でインストールして
{
"extends": [
"@linaria/stylelint-config-standard-linaria",
"stylelint-config-prettier"
],
"processors": ["stylelint-processor-styled-components"],
"files": ["**/*.{js,jsx,ts,tsx}"]
}
で設定。
これやる(Editor Setup)
scriptの設定
// (...略)
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
+ "lint": "npm run eslint-check-fix && npm run stylelint-check",
"preview": "vite preview",
+ "eslint-check-fix": "eslint . && prettier --write src/**/*.{ts,tsx}",
+ "stylelint-check": "stylelint-config-prettier-check '**/*.{js,jsx,ts,tsx}'"
},
// (...略)
とりあえずこれで。ダメだったらまた後で考える。
参考
脇道に逸れるけど知ったこと
VSCodeのNPMスクリプト ビュー
そんなことできたんだ...動画でやってて知った...
参考: https://www.youtube.com/watch?v=IrPz0kd2FTk
Git hooks + デプロイ + CI / CD などGitHub Actionsの設定
Git hooks (lintをGitHubコミット時にも実行する)
のインストールをして
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"lint": "npm run eslint-check-fix && npm run stylelint-check",
"preview": "vite preview",
"eslint-check-fix": "eslint . && prettier --write src/**/*.{ts,tsx}",
"stylelint-check": "stylelint-config-prettier-check '**/*.{js,jsx,ts,tsx}'",
"prepare": "husky"
},
+ "lint-staged": {
+ "**/*": "npm run lint"
+ },
コミット時にlintが走ることを確認
GitHub Actionsを学ぶ
入会しているITコミュニティ(TechCommit)の
で学習。メモ
運用監視
(続き)
一応これもみる
GitHub Actionsの作成
とりあえず、サンプルから適当に作った
問題
review dogのエラー
ハマちゃった。レビュードッグのことをもっと知らないと無理そう。下記見る
一応できたけど、時間がかかるのでまた考える。
Deploy失敗
Branch "main" is not allowed to deploy to github-pages due to environment protection rules.
これした。
デプロイはできたけど、真っ白のページ
何だっけ。前もあったな
これだったかな
下記の修正
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
// https://vitejs.dev/config/
export default defineConfig({
+ base: './',
plugins: [react()],
})
最終的なGitHub Actionsの内容
# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs
name: reviewdog
on:
pull_request:
branches: [ "dev" ]
jobs:
reviewdog:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
strategy:
matrix:
node-version: [22.x]
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
steps:
- uses: actions/checkout@v4
- name: misspell
uses: reviewdog/action-misspell@v1
with:
github_token: ${{ secrets.github_token }}
locale: "US"
- uses: EPMatt/reviewdog-action-prettier@v1
with:
github_token: ${{ secrets.github_token }}
# Change reviewdog reporter if you need
# [github-pr-check,github-check,github-pr-review].
# More about reviewdog reporters at
# https://github.com/reviewdog/reviewdog#reporters
reporter: github-pr-review
# Change reporter level if you need
# [info,warning,error].
# More about reviewdog reporter level at
# https://github.com/reviewdog/reviewdog#reporters
level: warning
- uses: reviewdog/action-eslint@v1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
reporter: github-pr-review # Change reporter.
eslint_flags: "src/"
- name: stylelint
uses: reviewdog/action-stylelint@v1
with:
reporter: github-pr-review # Change reporter.
stylelint_input: '**/*.css'
- uses: EPMatt/reviewdog-action-tsc@v1
with:
github_token: ${{ secrets.github_token }}
# Change reviewdog reporter if you need
# [github-pr-check,github-check,github-pr-review].
# More about reviewdog reporters at
# https://github.com/reviewdog/reviewdog#reporters
reporter: github-pr-review
# Change reporter level if you need
# [info,warning,error].
# More about reviewdog reporter level at
# https://github.com/reviewdog/reviewdog#reporters
level: warning
# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs
name: Node.js CI Test
on:
push:
branches: [ "dev" ]
pull_request:
branches: [ "dev" ]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [22.x]
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
steps:
- uses: actions/checkout@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- run: npm ci
# - run: npm test
# Simple workflow for deploying static content to GitHub Pages
name: Deploy react to GitHub Pages
on:
# Runs on pushes targeting the default branch
push:
branches: ["main"]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
# Single deploy job since we're just deploying
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Node
uses: actions/setup-node@v4
with:
node-version: 22.6.0
cache: "npm"
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Setup Pages
uses: actions/configure-pages@v5
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
# Upload entire repository
path: './dist'
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
デプロイページ
各ライブラリの動作確認
あとでかく
Vite
$ npm run dev
http://localhost:5173/
OK
React Routerのコードの書き方確認
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
+ import { createBrowserRouter, RouterProvider } from 'react-router-dom'
import App from './App.tsx'
import './index.css'
+ const router = createBrowserRouter([
+ {
+ path: '/',
+ element: <App />,
+ },
+ {
+ path: 'poke',
+ element: <div>poke</div>,
+ },
+ ])
createRoot(document.getElementById('root')!).render(
<StrictMode>
+ <RouterProvider router={router} />
- <App />
</StrictMode>
)
確認
Linariaのコードの書き方確認
あとで
Chart.jsのコードの書き方確認
あとで
画面作成
ちょっと体調不良で時間が空いてしまったので、まずはリスケ
1週間遅れかな。
一覧画面 作成
なんかuseEffectを使わないfetchの仕方があるって最近見た気がする。これかな?
今インストールされてるバージョンは
npm list react-router-dom
すると6.27.0
て出るから「React Router 6.4+」に該当するからそっちでできるっぽい。
参考: https://stackoverflow.com/questions/10972176/find-the-version-of-an-installed-npm-package参考: https://stackoverflow.com/questions/10972176/find-the-version-of-an-installed-npm-package
これかな?
suspenseと組み合わせる、と。
UI コンポーネントのインストール
今回、デザインは適当だけど1から作るの面倒なのでChakra UIを使うことにする(ChatGPTに適当に出してもらって、有名どころから適当に決めた)
npm i @chakra-ui/react @emotion/react
npx @chakra-ui/cli snippet add
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { createBrowserRouter, RouterProvider } from 'react-router-dom'
+ import { Provider } from './components/ui/provider'
import App from './App.tsx'
import './index.css'
const router = createBrowserRouter([
{
path: '/',
element: <App />,
},
{
path: 'poke',
element: <div>poke</div>,
},
])
createRoot(document.getElementById('root')!).render(
<StrictMode>
+ <Provider>
<RouterProvider router={router} />
+ </Provider>
</StrictMode>
)
一覧画面: とりあえず初期表示まで
async function fetchList() {
return fetch('https://pokeapi.co/api/v2/pokemon')
}
export { fetchList }
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { createBrowserRouter, RouterProvider } from 'react-router-dom'
import { Provider } from './components/ui/provider'
import App from './App.tsx'
+ import { fetchList } from './utils'
import './index.css'
const router = createBrowserRouter([
{
path: '/',
+ loader: fetchList,
element: <App />,
},
{
path: 'poke',
element: <div>poke</div>,
},
])
createRoot(document.getElementById('root')!).render(
<StrictMode>
<Provider>
<RouterProvider router={router} />
</Provider>
</StrictMode>
)
import { Suspense } from 'react'
import { useLoaderData } from 'react-router-dom'
import { Spinner, Flex, Card } from '@chakra-ui/react'
import './App.css'
function App() {
const listData: any = useLoaderData()
console.log(listData)
return (
<>
<header>
<h1>Pokemon app</h1>
</header>
<main>
<Flex>
<Suspense fallback={<Spinner />}>
{listData.results.map((pokemon: any) => (
<Card.Root maxW="sm" overflow="hidden">
<Card.Body>
<Card.Title>{pokemon.name}</Card.Title>
</Card.Body>
</Card.Root>
))}
</Suspense>
</Flex>
</main>
</>
)
}
export default App
とりあえず今日はここまで٩( ᐛ )و
2024/11/22 金 メモ
ちょっとLeetCodeで遊んでたら時間が空いた。
今日やること
ポートフォリオを作る数を減らすのでそれぞれの
- なぜ作ったか、
- どこまで作るのか
- スケジュール
を考える
作るもの
-
Pokemon App
- 基本のアプリでどこまで自分が作れるのかを表す
- React 基礎のおさらい、React18のキャッチアップ
- 品質として自分がどこまでを当たり前にできるのか(こだわっているのか)の探究
- ゼロランタイム CSS in JS を使用してみる
- グラフなど視覚的なインタラクティブアクションの勉強
- 規約バリバリのライブラリを入れチーム開発を意識して、とりあえず体験してみる
- GitHub Action CI/CDの体験、reviewDogの体験、dependBotの体験
- なんちゃって1人スクラムの実施
- 検索(インクリメンタルサーチ)を実装してみる体験
-
アンケートとアンケートの分析
- 応募する事業に関係するポートフォリオ(自分はこの辺ができますってアピール)
- Next.jsの基礎、Next.jsの最近のキャッチアップ
- コンポーネント設計(自分の現状と課題を知るため)
- 品質として自分がどこまでを当たり前にできるのか(こだわっているのか)の探究
- TailWindCSS
- AIなどでのアクションの勉強
- 規約バリバリのライブラリを入れチーム開発を意識して、経験値を踏む
- GitHub Action CI/CDの経験、reviewDogの経験
- なんちゃって1人スクラムの実施
- 認証、他認証
- T3 Stack、postgres
参考: これみて面白そうだなと思ったので自分でも作ってみる、て動機
-
LP
- ペライチ
- foriioのAPIを使う
- あんまり拘らない
Udemyの下記の教材は全部やる(supabaseとかあるから)
別途オンラインもくもく朝会でやってる、
とその次のReactのはオンラインもくもく朝会でそのままやって間に合う分だけポートフォリオに追加しておくポートフォリオはあまりみられないから丁寧に作って、自己分析や事業理解に力を入れる方針
2024/12/02 月 一覧画面作り込み
メモ
- Suspenseのchildren をasync のコンポーネントにできるってことだから、今回はreact-router-domのloaderでやるからSuspenseでなくてもいいのか?(もうちょっと作り込まないとよくわからないな)
↑ 勘違いっぽいasyncのコンポーネントできなかった
問題
fetch をローダでやると表示まで遅くて、Suspenseとfetchの組み合わせの仕方は自分は分かってない。明日、YouTubeとかみて勉強する