- node -v(volta list)
- npm create vite@latest smaple-app -- --template react-swc-ts
- npm run dev, build, preview
- tsconfig.json(path alias)
"compilerOptions": {
"baseUrl": "./",
"paths": {
"@/*": ["src/*"]
}
},
- npm i -D vite-tsconfig-paths (これで vite.config.ts は編集する必要なし)
- vite.config.ts
import react from "@vitejs/plugin-react-swc";
import { defineConfig } from "vite";
import tsconfigPaths from "vite-tsconfig-paths";
export default defineConfig({
plugins: [react(), tsconfigPaths()], //for path alias
});
-
npm install -D
vitest
happy-dom
@vitest/coverage-v8
@testing-library/react
@testing-library/user-event
@testing-library/jest-dom -
"coverage": "vitest run --coverage"
-
vite.config.ts
/// <reference types="vitest" />
import react from "@vitejs/plugin-react-swc";
import { defineConfig } from "vite";
import tsconfigPaths from "vite-tsconfig-paths";
export default defineConfig({
plugins: [react(), tsconfigPaths()],
test: {
// globals: true,
environment: "happy-dom",
setupFiles: ["./vitest-setup.ts"],
},
});
-
vitest-setup.ts(import "@testing-library/jest-dom/vitest")
-
tsconfig.json
{
"include": ["src", "vitest-setup.ts"]
}
- src/components/Count.tsx
// TextInput.js
import { useState } from "react";
const TextInput = () => {
const [text, setText] = useState("");
return (
<div>
<input
type="text"
value={text}
onChange={(e) => setText(e.target.value)}
placeholder="Enter some text"
aria-label="Text Input"
/>
<p>Entered Text: {text}</p>
</div>
);
};
export default TextInput;
- Count.test.tsx (and run coverage, test)
// TextInput.test.js
import userEvent from "@testing-library/user-event";
import { render, screen } from "@testing-library/react";
import TextInput from "./TextInput";
test("TextInput Component Test", async () => {
const user = userEvent.setup();
render(<TextInput />);
const inputElement = screen.getByLabelText("Text Input");
expect(screen.getByText("Entered Text:")).toBeInTheDocument();
await user.type(inputElement, "Hello World");
expect(screen.getByText("Entered Text: Hello World")).toBeInTheDocument();
});
-
npm install -D eslint, npx eslint --init
-
"lint": "eslint src" (added package.json), and npm run lint
-
.eslintrc.cjs
module.exports = {
env: {
browser: true,
es2021: true,
},
extends: [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:react/recommended",
],
overrides: [
{
env: {
node: true,
},
files: [".eslintrc.{js,cjs}"],
parserOptions: {
sourceType: "script",
},
},
],
parser: "@typescript-eslint/parser",
parserOptions: {
ecmaVersion: "latest",
sourceType: "module",
},
plugins: ["@typescript-eslint", "react"],
rules: {
"react/react-in-jsx-scope": "off",
},
};
-
mod a App.tsx a tag rel="noreferrer"
-
add some eslint roles (optional)
-
npm i -D prettier
/** @type {import("prettier").Config} */
const config = {};
export default config;
-
"lint": "eslint src"
-
"prettier plugin and settings.json format on save"
-
husky + lint-stataged
git init
npm install --save-dev husky lint-staged
npx husky install
npm pkg set scripts.prepare="husky install"
npx husky add .husky/pre-commit "npx lint-staged"
- pakage.json change and git add . git commit -m "init"
{
"lint-staged": {
"*.{js,jsx,ts,tsx,md}": ["prettier --write", "eslint --fix"]
},
"ignorePatterns": ["!.storybook"]
}
-
npx storybook init --builder @storybook/builder-vite
-
create storyBook directory and file (TextInput/TextInput.stories.tsx)
-
npm install -D tailwindcss postcss autoprefixer npx tailwindcss init -p
-
tailwind.config.js
/** @type {import('tailwindcss').Config} */
export default {
content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
theme: {
extend: {},
},
plugins: [],
};
- index.css
@tailwind base;
@tailwind components;
@tailwind utilities;
-
check className utility
-
npx shadcn-ui@latest init
-
Would you like to use TypeScript (recommended)? no / yes Which style would you like to use? › Default Which color would you like to use as base color? › Slate Where is your global CSS file? › › src/index.css Do you want to use CSS variables for colors? › no / yes Where is your tailwind.config.js located? › tailwind.config.js Configure the import alias for components: › @/components Configure the import alias for utils: › @/lib/utils Are you using React Server Components? › no / yes (no)
-
mod tailwind.config.js
/** @type {import('tailwindcss').Config} */
export default {
darkMode: ["class"],
content: [
"./pages/**/*.{ts,tsx}",
"./components/**/*.{ts,tsx}",
"./app/**/*.{ts,tsx}",
"./src/**/*.{ts,tsx}",
],
prefix: "",
theme: {
container: {
center: true,
padding: "2rem",
screens: {
"2xl": "1400px",
},
},
extend: {
colors: {
border: "hsl(var(--border))",
input: "hsl(var(--input))",
ring: "hsl(var(--ring))",
background: "hsl(var(--background))",
foreground: "hsl(var(--foreground))",
primary: {
DEFAULT: "hsl(var(--primary))",
foreground: "hsl(var(--primary-foreground))",
},
secondary: {
DEFAULT: "hsl(var(--secondary))",
foreground: "hsl(var(--secondary-foreground))",
},
destructive: {
DEFAULT: "hsl(var(--destructive))",
foreground: "hsl(var(--destructive-foreground))",
},
muted: {
DEFAULT: "hsl(var(--muted))",
foreground: "hsl(var(--muted-foreground))",
},
accent: {
DEFAULT: "hsl(var(--accent))",
foreground: "hsl(var(--accent-foreground))",
},
popover: {
DEFAULT: "hsl(var(--popover))",
foreground: "hsl(var(--popover-foreground))",
},
card: {
DEFAULT: "hsl(var(--card))",
foreground: "hsl(var(--card-foreground))",
},
},
borderRadius: {
lg: "var(--radius)",
md: "calc(var(--radius) - 2px)",
sm: "calc(var(--radius) - 4px)",
},
keyframes: {
"accordion-down": {
from: { height: "0" },
to: { height: "var(--radix-accordion-content-height)" },
},
"accordion-up": {
from: { height: "var(--radix-accordion-content-height)" },
to: { height: "0" },
},
},
animation: {
"accordion-down": "accordion-down 0.2s ease-out",
"accordion-up": "accordion-up 0.2s ease-out",
},
},
},
plugins: [import("tailwindcss-animate")],
};
-
npx shadcn-ui@latest add button
-
github actions setup
-
.github/workflows/lint.yml & test.yml
name: Lint
on: push
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
- run: npm ci
- run: npm run lint
name: Test
on: push
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
- run: npm ci
- run: npm run test
or lint_test.yml
name: Lint and Test
on: push
jobs:
lint-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: "20"
- name: Install Dependencies
run: npm ci
- name: Run Lint
run: npm run lint
- name: Run Test
run: npm run test
- CD(Vite 静的ホスティング参照)
https://zenn.dev/tentel/articles/488dd8765fb059 https://zenn.dev/kazukix/articles/react-setup-2024