create-react-app is dead
以下の記事が凄くわかりやすいです。
一部引用
Releasesを見ていくと、最後のリリースは去年の4月です。近年のリリース日をまとめるとこんな感じです。
viteに移行しましょう。ついでにpnpmにも入門してみます。
今回は、以下をやってみます!
① pnpmインストール
② vite + react 環境作成
③ vitest インストール
④ vitest + React Testing Library 環境作成
0⃣ ver確認
node -v # v20.9.0
pnpm -v # 9.11.0
① pnpmのインストール
公式ドキュメントを見つつ、お好みの方法でインストールします
nodeはデフォルトでnpmもおまけにインストールしてくれているはずなので、これがシンプルで楽なはず
npm install -g pnpm
そもそもpnpmって?
npmのお兄ちゃん
特に
- npmに比べ動作が速い
- node_modulesをプロジェクト間で共有する
の2点が趣味開発してるマシン的には嬉しいと思いました
② vite + react環境の作成
ドキュメントに従い、 create vite
コマンドでプロジェクトを作成します
create viteコマンドでプロジェクトを作成する
pnpm create vite my-react-ts-app --template react-ts
一瞬で終わる!
昔create-react-appしたときより早い気がする。きのせい?
c/work/react$ pnpm create vite my-react-ts-app --template react-ts
Scaffolding project in c/work/react/my-react-ts-app...
Done. Now run:
cd my-react-ts-app
pnpm install
pnpm run dev
コマンドラインに従い、パッケージのインストールとreact devサーバーの起動を行ってみます
cd my-react-ts-app
pnpm install
pnpm run dev
pnpmコマンドでパッケージをインストール
pnpm install
実行します。
c/work/react/my-react-ts-app$ pnpm install
╭──────────────────────────────────────────────────────────────────╮
│ │
│ Update available! 9.11.0 → 9.12.0. │
│ Changelog: https://github.com/pnpm/pnpm/releases/tag/v9.12.0 │
│ Run "pnpm add -g pnpm" to update. │
│ │
│ Follow @pnpmjs for updates: https://x.com/pnpmjs │
│ │
╰──────────────────────────────────────────────────────────────────╯
Packages: +192
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Progress: resolved 229, reused 140, downloaded 52, added 192, done
dependencies:
+ react 18.3.1
+ react-dom 18.3.1
devDependencies:
+ @eslint/js 9.12.0
+ @types/react 18.3.11
+ @types/react-dom 18.3.0
+ @vitejs/plugin-react 4.3.2
+ eslint 9.12.0
+ eslint-plugin-react-hooks 5.1.0-rc-fb9a90fa48-20240614
+ eslint-plugin-react-refresh 0.4.12
+ globals 15.10.0
+ typescript 5.6.2
+ typescript-eslint 8.8.0
+ vite 5.4.8
Done in 1m 31.6s
Done in 1m 31.6s
早い!気がします
react devサーバーを実行
pnpm run dev
実行します
c/work/react/my-react-ts-app$ pnpm run dev
> my-react-ts-app@0.0.0 dev c/work/react/my-react-ts-app
> vite
VITE v5.4.8 ready in 4632 ms
➜ Local: http://localhost:5173/
➜ Network: use --host to expose
➜ press h + enter to show help
VITE v5.4.8 ready in 4632 ms
早い!気がします
http://localhost:5173/
で問題なく表示されていることを確認します
とにかく早いですねー
③ vitest インストール
テストライブラリもインストールしていきます。
vitestのインストール
ドキュメントに従ってインストールしていきます。
pnpm add -D vitest
実行します
c/work/react/my-react-ts-app$ pnpm add -D vitest
Packages: +29
+++++++++++++++++++++++++++++
Progress: resolved 258, reused 212, downloaded 9, added 29, done
devDependencies:
+ vitest 2.1.2
Done in 28.3s
インストールされました
vitestを実行してみる
testファイルを作成していきます
mkdir __test__
touch __test__/sample.test.ts
テストを書いてみます
import { describe, expect, it } from "vitest";
describe("sample", () => {
it("1 eq 1", () => {
expect(1).toBe(1)
})
})
テストが実行できるよう、package.jsonを編集します
"dev": "vite",
+ "test":"vitest",
"build": "tsc -b && vite build",
testスクリプトを追記します
{
"name": "my-react-ts-app",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"test":"vitest",
"build": "tsc -b && vite build",
"lint": "eslint .",
"preview": "vite preview"
},
"dependencies": {
"react": "^18.3.1",
"react-dom": "^18.3.1"
},
"devDependencies": {
"@eslint/js": "^9.11.1",
"@types/react": "^18.3.10",
"@types/react-dom": "^18.3.0",
"@vitejs/plugin-react": "^4.3.2",
"eslint": "^9.11.1",
"eslint-plugin-react-hooks": "^5.1.0-rc.0",
"eslint-plugin-react-refresh": "^0.4.12",
"globals": "^15.9.0",
"typescript": "^5.5.3",
"typescript-eslint": "^8.7.0",
"vite": "^5.4.8",
"vitest": "^2.1.2"
}
}
では、テストを実行して1は1なのか確かめます
pnpm run test
コマンドを実行します
c/work/react/my-react-ts-app$ pnpm run test
> my-react-ts-app@0.0.0 test c/work/react/my-react-ts-app
> vitest
DEV v2.1.2 c/work/react/my-react-ts-app
✓ __test__/sample.test.ts (1)
✓ sample (1)
✓ 1 eq 1
Test Files 1 passed (1)
Tests 1 passed (1)
Start at 09:39:24
Duration 9.43s (transform 268ms, setup 0ms, collect 789ms, tests 7ms, environment 1ms,
prepare 6.44s)
PASS Waiting for file changes...
press h to show help, press q to quit
✓ 1 eq 1
良い感じですね
そもそもvitestって?
jestライクなテスティングライブラリです
特に
- viteと統合されている(から?HMRがはやい)
- ESM, CJSを意識しなくていい(はず)
- jestライク
の3点が個人的嬉しいところです
④ vitest + React Testing Library 環境作成
実行環境を提供するライブラリのインストール
node環境上には、デフォルトではDOMを再現する機能が存在しません
DOMを再現するためのライブラリをインストールします
pnpm add -D jsdom
コマンドを実行します
c/work/react/my-react-ts-app$ pnpm add -D jsdom
Packages: +36
++++++++++++++++++++++++++++++++++++
Progress: resolved 293, reused 227, downloaded 29, added 36, done
devDependencies:
+ jsdom 25.0.1
Done in 53.5s
インストール後、vite.config.ts を編集します
+ // Vitestの型を追加する
+ /// <reference types="vitest" />
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
+ test: {
+ // デフォルトのnode環境ではDOMを再現できないので、jsdom環境を使用する
+ environment: "jsdom",
+ },
})
準備完了です!!!
// Vitestの型を追加する
/// <reference types="vitest" />
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
test: {
// デフォルトのnode環境ではDOMを再現できない
environment: "jsdom",
},
})
Reactコンポーネントをテストするためのライブラリをインストールする
Reactはjsx、tsxという特殊な形式のjs、tsを利用します
デフォルトのvitest、jsdomだけではこのReactコンポーネントをレンダリングしたり、操作できません
そこで、Reactコンポーネントをレンダリング・操作するためのライブラリを別途追加します
pnpm add -D @testing-library/react @testing-library/jest-dom @testing-library/user-event
コマンドを実行します
c/work/react/my-react-ts-app$ pnpm add -D @testing-library/react
@testing-library/jest-dom @testing-library/user-event
Packages: +25
+++++++++++++++++++++++++
Progress: resolved 318, reused 257, downloaded 24, added 25, done
devDependencies:
+ @testing-library/jest-dom 6.5.0
+ @testing-library/react 16.0.1
+ @testing-library/user-event 14.5.2
Done in 1m 2.9s
テストを書いてみます
touch __test__/App.test.tsx
こんな感じのテストケースを用意しました。
import { beforeEach, describe, expect, it } from "vitest";
import { cleanup, render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import '@testing-library/jest-dom/vitest';
import React from "react";
import App from "../src/App"
// デフォルトではクリーンアップされないため、Eachで実行する
beforeEach(() => {
cleanup();
});
// userインスタンスのセットアップ
const user = userEvent.setup();
describe("tsx sample", () => {
it("viteとReactの画像が表示されていることを確認する", () => {
// コンポーネントをレンダリングする
render(<App />)
// レンダリングされたDOM上から要素を取得する
const imgElementArray = screen.getAllByRole("img")
// アサートする
// 本来はテストケースごとに1アサーションが良いってt-wadaさんが言ってた
expect(imgElementArray.length).toBe(2)
expect(imgElementArray[0].getAttribute("alt")).toBe("Vite logo")
expect(imgElementArray[1].getAttribute("alt")).toBe("React logo")
})
it("use jest-dom sample", () => {
// コンポーネントをレンダリングする
render(<App />)
// 拡張されたマッチャーを使用できる
expect(screen.getByText("count is 0")).toBeInTheDocument()
})
it("use user-event sample", async () /* async関数をテストケース内で使用する */ => {
// コンポーネントをレンダリングする
render(<App />)
// レンダリングされたDOM上から要素を取得する
const countButtonElement = screen.getByRole("button")
// userの操作を再現する
// clickはasync関数なので、awaitする
await user.click(countButtonElement)
// 拡張されたマッチャーを使用できる
expect(screen.getByText("count is 1")).toBeInTheDocument()
})
})
先ほどaddした以下のライブラリが何をしてくれているか確認します
@testing-library/react
@testing-library/jest-dom
@testing-library/user-event
@testing-library/react
import { cleanup, render, screen } from "@testing-library/react";
@testing-library/react
は、上述したように、
render
関数やscreen
関数で、Reactコンポーネントをレンダリングしてくれています。
// コンポーネントをレンダリングする
render(<App />)
// レンダリングされたDOM上から要素を取得する
const imgElementArray = screen.getAllByRole("img")
こんなかんじですね
@testing-library/jest-dom
import '@testing-library/jest-dom/vitest';
jest-domはvitestのマッチャー(比較するメソッド)を拡張してくれています
// 拡張されたマッチャーを使用できる
expect(screen.getByText("count is 0")).toBeInTheDocument()
今回は toBeInTheDocument()
マッチャーを使ってみてます
@testing-library/user-event
import userEvent from "@testing-library/user-event";
@testing-library/user-event
は、上述したように、
DOMに対するユーザーの操作を疑似的に再現してくれています。
// userインスタンスのセットアップ
const user = userEvent.setup();
const countButtonElement = screen.getByRole("button")
// userの操作を再現する
// clickはasync関数なので、awaitする
await user.click(countButtonElement)
くりっくしてくれます
テストコードはこんな感じなので、テストを実行してみます
c/work/react/my-react-ts-app$ pnpm run test
> my-react-ts-app@0.0.0 test c/work/react/my-react-ts-app
> vitest
DEV v2.1.2 c/work/react/my-react-ts-app
✓ __test__/App.test.tsx (3) 387ms
✓ tsx sample (3) 385ms
✓ viteとReactの画像が表示されていることを確認する
✓ use jest-dom sample
✓ use user-event sample
Test Files 1 passed (1)
Tests 3 passed (3)
Start at 10:57:57
Duration 93.69s (transform 822ms, setup 0ms, collect 36.01s, tests 387ms, environment 47.37s, prepare 7.85s)
PASS Waiting for file changes...
press h to show help, press q to quit
やったー
これで超基本の部分の環境構築は完了したかなーと思います!