Vite, React 18, Recoil, Storybook がある程度安定してきたので構築してみる
今回の環境
TL;DR
1. とりあえずサンプルプロジェクトを作る
vite react-ts
npm -y create vite@latest
? Project name: › vite-project
? Select a framework: › - Use arrow-keys. Return to submit.
Vanilla
Vue
❯ React
Preact
Lit
Svelte
? Select a variant: › - Use arrow-keys. Return to submit.
JavaScript
❯ TypeScript
Scaffolding project in ./vite-project...
Done. Now run:
cd vite-project
npm install
npm run dev
cd vite-project
npm install
added 88 packages, and audited 89 packages in 494ms
8 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
npm run dev
> vite-project@0.0.0 dev
> vite
VITE v3.1.3 ready in 387 ms
➜ Local: http://localhost:5173/
➜ Network: use --host to expose
eslint
npm init -y @eslint/config
? How would you like to use ESLint? …
To check syntax only
To check syntax and find problems
▸ To check syntax, find problems, and enforce code style
? What type of modules does your project use? …
▸ JavaScript modules (import/export)
CommonJS (require/exports)
None of these
? Which framework does your project use? …
▸ React
Vue.js
None of these
? Does your project use TypeScript? No / ‣ Yes
? Where does your code run? … (Press <space> to select, <a> to toggle all, <i> to invert selection)
✔ Browser
Node
? How would you like to define a style for your project? …
▸ Use a popular style guide
Answer questions about your style
? Which style guide do you want to follow? …
▸ Standard: https://github.com/standard/eslint-config-standard-with-typescript
XO: https://github.com/xojs/eslint-config-xo-typescript
? What format do you want your config file to be in? …
JavaScript
YAML
▸ JSON
Checking peerDependencies of eslint-config-standard-with-typescript@latest
Local ESLint installation not found.
The config that you've selected requires the following dependencies:
eslint-plugin-react@latest eslint-config-standard-with-typescript@latest @typescript-eslint/eslint-plugin@^5.0.0 eslint@^8.0.1 eslint-plugin-import@^2.25.2 eslint-plugin-n@^15.0.0 eslint-plugin-promise@^6.0.0 typescript@*
? Would you like to install them now? No / ‣ Yes
? Which package manager do you want to use? …
▸ npm
yarn
pnpm
added 199 packages, and audited 288 packages in 8s
85 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
Successfully created .eslintrc.json file in ./vite-project
// .eslintrc.json
{
...
"extends": [
"plugin:react/recommended",
+ "plugin:react/jsx-runtime",
"standard-with-typescript"
],
...
"parserOptions": {
"ecmaVersion": "latest",
+ "project": "./tsconfig.json",
"sourceType": "module"
},
...
"rules": {
+ "@typescript-eslint/explicit-function-return-type": "off"
+ },
+ "settings": {
+ "react": {
+ "version": "detect"
+ }
}
}
// src/vite-env.d.ts
+ // eslint-disable-next-line @typescript-eslint/triple-slash-reference
/// <reference types="vite/client" />
prettier
npm install --save-dev eslint-config-prettier
added 1 package, and audited 289 packages in 546ms
85 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
npm install --save-dev --save-exact prettier
added 1 package, and audited 290 packages in 566ms
86 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
echo '{ "semi": false, "singleQuote": true }'> .prettierrc.json
// .eslintrc.json
{
...
"extends": [
...
- "standard-with-typescript"
+ "standard-with-typescript",
+ "prettier"
],
...
}
recoil
npm install --save-dev eslint-plugin-react-hooks
added 1 package, and audited 291 packages in 850ms
86 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
npm install recoil
added 2 packages, and audited 293 packages in 914ms
86 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
// .eslintrc.json
{
...
"extends": [
"plugin:react/recommended",
"plugin:react/jsx-runtime",
+ "plugin:react-hooks/recommended",
"standard-with-typescript",
"prettier"
],
...
"plugins": [
- "react"
+ "react",
+ "react-hooks"
],
"rules": {
- "@typescript-eslint/explicit-function-return-type": "off"
+ "@typescript-eslint/explicit-function-return-type": "off",
+ "react-hooks/rules-of-hooks": "error",
+ "react-hooks/exhaustive-deps": [
+ "warn", {
+ "additionalHooks": "(useRecoilCallback|useRecoilTransaction_UNSTABLE)"
+ }
+ ]
}
}
// src/recoil/counter/atom.ts
+ import { atom } from 'recoil'
+
+ const countState = atom({
+ key: 'countState', // unique ID (with respect to other atoms/selectors)
+ default: 0, // default value (aka initial value)
+ })
+
+ export default countState
+
// src/recoil/counter/index.ts
+ import atom from './atom'
+
+ export default atom
+
// src/components/Counter.tsx
+ import { useRecoilState } from 'recoil'
+ import reactLogo from '../assets/react.svg'
+ import countState from '../recoil/counter'
+
+ function Counter() {
+ const [count, setCount] = useRecoilState(countState)
+
+ return (
+ <>
+ <div>
+ <a href="https://vitejs.dev" target="_blank" rel="noreferrer">
+ <img src="/vite.svg" className="logo" alt="Vite logo" />
+ </a>
+ <a href="https://reactjs.org" target="_blank" rel="noreferrer">
+ <img src={reactLogo} className="logo react" alt="React logo" />
+ </a>
+ </div>
+ <h1>Vite + React + Recoil</h1>
+ <div className="card">
+ <button onClick={() => setCount((count) => count + 1)}>
+ count is {count}
+ </button>
+ <p>
+ Edit <code>src/App.tsx</code> and save to test HMR
+ </p>
+ </div>
+ <p className="read-the-docs">
+ Click on the Vite and React logos to learn more
+ </p>
+ </>
+ )
+ }
+
+ export default Counter
+
// src/App.tsx
- import { useState } from 'react'
- import reactLogo from './assets/react.svg'
+ import { RecoilRoot } from 'recoil'
+ import Counter from './components/Counter'
import './App.css'
function App() {
- const [count, setCount] = useState(0)
-
return (
- <div className="App">
- <div>
- <a href="https://vitejs.dev" target="_blank" rel="noreferrer">
- <img src="/vite.svg" className="logo" alt="Vite logo" />
- </a>
- <a href="https://reactjs.org" target="_blank" rel="noreferrer">
- <img src={reactLogo} className="logo react" alt="React logo" />
- </a>
- </div>
- <h1>Vite + React</h1>
- <div className="card">
- <button onClick={() => setCount((count) => count + 1)}>
- count is {count}
- </button>
- <p>
- Edit <code>src/App.tsx</code> and save to test HMR
- </p>
- </div>
- <p className="read-the-docs">
- Click on the Vite and React logos to learn more
- </p>
- </div>
+ <RecoilRoot>
+ <CharacterCounter />
+ </RecoilRoot>
)
}
export default App
<!--- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
...
- <title>Vite + React + TS</title>
+ <title>Vite + React + TS + Recoil</title>
</head>
...
</html>
tailwind
npm install -D tailwindcss postcss autoprefixer
added 36 packages, and audited 331 packages in 2s
93 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
npx tailwindcss init -p
Created Tailwind CSS config file: tailwind.config.cjs
Created PostCSS config file: postcss.config.cjs
// postcss.config.cjs
/** @type {import('tailwindcss').Config} */
module.exports = {
- content: [],
+ content: [
+ "./index.html",
+ "./src/**/*.{js,ts,jsx,tsx}",
+ ],
...
}
/* src/App.css */
- #root {
- max-width: 1280px;
- margin: 0 auto;
- padding: 2rem;
- text-align: center;
- }
...
<!--- index.html -->
<!DOCTYPE html>
<html lang="en">
...
<body>
- <div id="root"></div>
+ <div id="root" class="max-w-7xl my-0 mx-auto p-8 text-center"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
stylelint
npm install --save-dev stylelint stylelint-config-standard stylelint-config-prettier prettier-plugin-tailwindcss
added 94 packages, and audited 425 packages in 1s
107 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
// .stylelintrc.json
+ {
+ "extends": [
+ "stylelint-config-standard",
+ "stylelint-config-prettier"
+ ],
+ "rules": {
+ "at-rule-no-unknown": [
+ true,
+ {
+ "ignoreAtRules": [
+ "tailwind",
+ "apply",
+ "variants",
+ "responsive",
+ "screen"
+ ]
+ }
+ ],
+ "declaration-block-trailing-semicolon": null,
+ "no-descending-specificity": null
+ }
+ }
+
// .prettierrc.json
- { "semi": false, "singleQuote": true }
+ {
+ "plugins": [
+ "prettier-plugin-tailwindcss"
+ ],
+ "semi": false,
+ "singleQuote": true,
+ "tailwindConfig": "./tailwind.config.cjs"
+ }
2. Storybook を入れる
storybook
npx -y sb init --builder @storybook/builder-vite
storybook init - the simplest way to add a Storybook to your project.
• Detecting project type. ✓
• Adding Storybook support to your "React" app
attention => Storybook now collects completely anonymous telemetry regarding usage.
This information is used to shape Storybook's roadmap and prioritize features.
You can learn more, including how to opt-out if you'd not like to participate in this anonymous program, by visiting the following URL:
https://storybook.js.org/telemetry
added 1365 packages, and audited 1696 packages in 44s
266 packages are looking for funding
run `npm fund` for details
22 high severity vulnerabilities
To address issues that do not require attention, run:
npm audit fix
To address all issues (including breaking changes), run:
npm audit fix --force
Run `npm audit` for details.
. ✓
• Preparing to install dependencies. ✓
• Installing dependencies
up to date, audited 1696 packages in 2s
266 packages are looking for funding
run `npm fund` for details
22 high severity vulnerabilities
To address issues that do not require attention, run:
npm audit fix
To address all issues (including breaking changes), run:
npm audit fix --force
Run `npm audit` for details.
. ✓
🔎 checking possible migrations..
🔎 found a 'eslintPlugin' migration:
╭──────────────────────────────────────────────────────────────────────╮
│ │
│ We've detected you are not using our eslint-plugin. │
│ │
│ In order to have the best experience with Storybook and follow │
│ best practices, we advise you to install │
│ eslint-plugin-storybook. │
│ │
│ More info: │
│ https://github.com/storybookjs/eslint-plugin-storybook#readme │
│ │
╰──────────────────────────────────────────────────────────────────────╯
? Do you want to run the 'eslintPlugin' migration on your project? › (y/N) yes
✅ Adding dependencies: eslint-plugin-storybook
added 4 packages, and audited 1700 packages in 11s
267 packages are looking for funding
run `npm fund` for details
22 high severity vulnerabilities
To address issues that do not require attention, run:
npm audit fix
To address all issues (including breaking changes), run:
npm audit fix --force
Run `npm audit` for details.
✅ Configuring eslint rules in .eslintrc.json
✅ Adding Storybook to extends list
✅ ran eslintPlugin migration
🔎 found a 'npm7' migration:
╭──────────────────────────────────────────────────────────────────────╮
│ │
│ We've detected you are running npm 8.15.0 │
│ which has peer dependency semantics which Storybook is │
│ incompatible with. │
│ │
│ In order to work with Storybook's package structure, you'll need │
│ to run `npm` with the │
│ `--legacy-peer-deps=true` flag. We can generate an `.npmrc` │
│ which will do that automatically. │
│ │
│ More info: https://github.com/storybookjs/storybook/issues/18298 │
│ │
╰──────────────────────────────────────────────────────────────────────╯
? Do you want to run the 'npm7' migration on your project? › (y/N) yes
✅ ran npm7 migration
✅ migration check successfully ran
To run your Storybook, type:
npm run storybook
3. 表示してみる
npm run storybook
╭─────────────────────────────────────────────────╮
│ │
│ Storybook 6.5.10 for React started │
│ 8.6 s for manager and 4.1 s for preview │
│ │
│ Local: http://localhost:6006/ │
│ On your network: http://0.0.0.0:6006/ │
│ │
╰─────────────────────────────────────────────────╯
ここまで