今Reactで新規PJを作るなら 2022
バンドラー:Vite
理由:速いは正義 全ての効率を向上させてくれる
TypeScriptは大前提
スタイリング候補
- styled-component
- linaria
- emotion
一旦linariaで試す
時間があったらCSS in JSは一通り試したい
そしてStyledXに期待
tree -I "node_modules|dist"
.
├── index.html
├── package.json
├── public
│ └── favicon.svg
├── src
│ ├── App.tsx
│ ├── main.tsx
│ └── vite-env.d.ts
├── tsconfig.json
├── tsconfig.node.json
├── vite.config.ts
└── yarn.lock
2 directories, 10 files
とりあえずlint
module.exports = {
env: {
browser: true,
es2021: true,
node: true,
},
extends: [
"eslint:recommended",
"plugin:react/recommended",
"plugin:react-hooks/recommended",
"plugin:@typescript-eslint/recommended",
"prettier",
],
parser: "@typescript-eslint/parser",
parserOptions: {
ecmaFeatures: {
jsx: true,
},
ecmaVersion: "latest",
sourceType: "module",
},
plugins: ["react", "@typescript-eslint"],
rules: {},
settings: {
react: {
version: "detect",
},
},
}
React18でこれを指定しないとwarningがでた
Warning: React version not specified in eslint-plugin-react settings. See https://github.com/yannickcr/eslint-plugin-react#configuration .
settings: {
react: {
version: "detect",
},
},
現時点のpackage.json
{
"name": "react-template",
"private": true,
"version": "0.0.0",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"preview": "vite preview",
"format": "prettier --write ./src/**/*.{ts,tsx}",
"lint": "eslint --ext ts,tsx .",
"lint:fix": "yarn lint --fix"
},
"dependencies": {
"react": "18.0.0",
"react-dom": "18.0.0"
},
"devDependencies": {
"@types/react": "18.0.0",
"@types/react-dom": "18.0.0",
"@typescript-eslint/eslint-plugin": "5.20.0",
"@typescript-eslint/parser": "5.20.0",
"@vitejs/plugin-react": "1.3.0",
"eslint": "8.14.0",
"eslint-config-prettier": "8.5.0",
"eslint-plugin-react": "7.29.4",
"eslint-plugin-react-hooks": "4.4.0",
"prettier": "2.6.2",
"typescript": "4.6.3",
"vite": "2.9.5"
}
}
ルーティング: react-router-dom@v6
理由:デファクトスタンダードのため(破壊的変更を繰り返してるのが心配だけど...)
tsconfigのpathを自動でマッピングしてくれるプラグイン
依存増やしたくないマンなのでとりあえず使わないけどPJが大きくなってaliasも複数貼るなら便利そう
このレポジトリに随時pushしている
現時点のdir
.
├── .eslintignore
├── .eslintrc.js
├── .gitignore
├── .prettierrc
├── index.html
├── package.json
├── public
│ └── favicon.svg
├── src
│ ├── App.tsx
│ ├── assets
│ │ └── .gitkeep
│ ├── components
│ │ └── Button
│ │ └── .gitkeep
│ ├── context
│ │ └── .gitkeep
│ ├── features
│ │ ├── objective
│ │ │ └── .gitkeep
│ │ └── user
│ │ └── .gitkeep
│ ├── hooks
│ │ └── .gitkeep
│ ├── lib
│ │ └── .gitkeep
│ ├── main.tsx
│ ├── pages
│ │ └── .gitkeep
│ ├── routes
│ │ ├── index.ts
│ │ └── routes.tsx
│ ├── utils
│ │ └── .gitkeep
│ └── vite-env.d.ts
├── tsconfig.json
├── tsconfig.node.json
├── vite.config.ts
└── yarn.lock
14 directories, 25 files
linaria、ドキュメントこれだけなのか...
(全部githubに飛ばされる)
stylingはstyled-componentsを採用する
理由
- 候補だったlinariaはviteの正式サポートがなく不安が残る
- パフォーマンスは困ったときに対応したらいい
- styled-componentsはなんだかんだデファクトでありメンタルモデルが働く
セバスチャンさんがzero runtimeのCSSライブラリを推奨してる...
はやくStyledXを公開してくれ
stylingはやっぱりvanilla-extractを採用する
.css.tsというファイルを強制してくるのがうーんだけど慣れるかもしれないという期待をしている
あとviteをサポートしているのが強い
参考にさせていただいた
Reactは当然18
Vitestを触ってみる
特に問題なければ採用するかも
vanilla-extractと相性が悪い
rollupのプラグイン使ってbabelのプラグイン噛ませてもダメ
FAIL src/components/Spinner/spinner.test.tsx [ src/components/Spinner/spinner.test.tsx ]
Error: Styles were unable to be assigned to a file. This is generally caused by one of the following:
- You may have created styles outside of a '.css.ts' context
- You may have incorrect configuration. See https://vanilla-extract.style/documentation/setup
issueもいくつかあがってる
一旦vitestは様子見することにする
babel書いてやっとテストできるようになった
ここまできたらvanilla-extractやめてもいい気持ちになってきた
せっかくだしvitestを使いたい気持ちが拭えない
styled-componentならいけるのか試すことにする
vanilaの供養
import { keyframes } from "@vanilla-extract/css"
import * as V from "@vanilla-extract/recipes"
const rotate = keyframes({
"0%": { transform: "rotate(0deg)" },
"100%": { transform: "rotate(360deg)" },
})
export const recipe = V.recipe({
base: {
borderStyle: "solid",
borderRadius: "99999px",
borderWidth: "2px",
borderBottomColor: "transparent",
borderLeftColor: "transparent",
animation: `${rotate} 0.45s linear infinite`,
},
variants: {
size: {
sm: {
width: "16px",
height: "16px",
},
md: {
width: "24px",
height: "24px",
},
},
},
defaultVariants: {
size: "md",
},
})
export type Variants = V.RecipeVariants<typeof recipe>
ふとRomeの存在を思い出した
styled-componentsのv6を試しに入れてみたらbuildできず
v5にする
✘ [ERROR] No matching export in "node_modules/tslib/tslib.es6.js" for import "__spreadArray"
node_modules/styled-components/dist/styled-components.browser.esm.js:1:7:
1 │ import{__spreadArray as e,__read as t,__values as n,__assign as o,__rest as r}from"tslib";import i ...
╵ ~~~~~~~~~~~~~
23:27:50 [vite] error while updating dependencies:
Error: Build failed with 1 error:
node_modules/styled-components/dist/styled-components.browser.esm.js:1:7: ERROR: No matching export in "node_modules/tslib/tslib.es6.js" for import "__spreadArray"
これはstyled-componentsが依存してるtslibのバージョンが低いことが原因
testing系は以下を採用
- vitest
- testing-library
stylingは結局styled-components
今日はここまで
残り
- api client
- storybook
- アプリケーション実装
いまからやる
Storybookの導入から
errorboudaryつくる
18でも特に変わったことなし
ただsuspenseをたくさん活用したいので、ErrorBoundaryも複数箇所で使えるようにかいた
import * as React from "react"
type Props = {
onError?: (err: unknown) => void
fallback: (err: unknown) => React.ReactNode
children: React.ReactNode
}
type State = {
cause: unknown | null
}
export class ErrorBoundary extends React.Component<Props, State> {
constructor(props: Props) {
super(props)
this.state = {
cause: null,
}
}
static getDerivedStateFromError(cause: unknown) {
return { cause }
}
componentDidCatch(error: unknown, _info: React.ErrorInfo) {
if (!this.props.onError) return
this.props.onError(error)
}
render() {
const { cause } = this.state
if (cause) {
return this.props.fallback(cause)
}
return this.props.children
}
}