何か新しいものを作ろうとしたときに、毎回調べている気がするのでまとめてみた。
最近はWeb(Next.js)+Desktop(Tauri+Vite+React)で作ることが多いので、なんだかんだ偏っているけどnpm使うなら使えるはず
プロジェクトの構造を作る#
基本的にpnpmを使う
pnpm init --init-type module
モノレポでやる場合はpnpm-workspace.yamlを追加する
大体こんな感じのディレクトリ構造でやることが多い desktopとwebのフォルダはpnpm create ほにゃららが作るので自分では作らない
tree .
.
├── apps
│ ├── desktop
│ └── web
└── packages
├── ui
└── utils
7 directories, 0 files
Next.js#
こんな感じで作成する ESLintではなくBiomeを使う
create next-app@latest web
✔ Would you like to use the recommended Next.js defaults? › No, customize settings
✔ Would you like to use TypeScript? … No / Yes
✔ Which linter would you like to use? › Biome
✔ Would you like to use React Compiler? … No / Yes
✔ Would you like to use Tailwind CSS? … No / Yes
✔ Would you like your code inside a `src/` directory? … No / Yes
✔ Would you like to use App Router? (recommended) … No / Yes
✔ Would you like to customize the import alias (`@/*` by default)? … No / Yes
✔ What import alias would you like configured? … @/*
pnpm-workspace.yamlとbiome.jsonが作成されるが、プロジェクトルートで作成するので必要に応じて削除する。
Tauri#
Rustがインストールされていることを確認する
pnpm create tauri-app
✔ Project name · desktop
✔ Identifier · dev.usbharu.test
✔ Choose which language to use for your frontend · TypeScript / JavaScript - (pnpm, yarn, npm, deno, bun)
✔ Choose your package manager · pnpm
✔ Choose your UI template · React - (https://react.dev/)
✔ Choose your UI flavor · TypeScript
TypeScript#
pnpm add -D typescript
npx tsc --init
npm scriptにtypecheckを追加しておく 正直いらないが… AIが利用できるコマンドを制限するときに楽
"typecheck": "tsc --noEmit"
Vite(ライブラリモード)#
npmに公開するかはともかくライブラリを作るときはViteのライブラリモードを利用するといいらしい やったことない
https://ja.vite.dev/guide/build#library-mode
単にモノレポの1パッケージとして作るだけなら不要
pnpmでモノレポ内のパッケージを追加する場合
pnpm add --workspace @test/ui
npmではやったことないけど、バージョンカタログの仕組みであるpnpm catalogで管理するというのもいいかも
テストとか諸々#
Biome#
Biome君VSCodeの拡張機能がちょっと残念だけど基本的に優秀なので使ってます
https://biomejs.dev/ja/guides/getting-started/#%E8%A8%AD%E5%AE%9A
pnpm add -w -D @biomejs/biome
pnpm exec biome init
- JSONスキーマをURLからnode_modules内のファイルに変える
- 自動的にインストールされているバージョンのスキーマを使うことができる
- useIgnoreFile
- *.d.tsファイルの除外
- tailwindcss対応
{
"$schema": "./node_modules/@biomejs/biome/configuration_schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
},
"files": {
"ignoreUnknown": true,
"includes": ["**", "!**/*.d.ts"]
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2
},
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"a11y": {
"noStaticElementInteractions": "off"
},
"nursery": {
"useSortedClasses": {
"fix": "safe",
"level": "error",
"options": {
"functions": ["twMerge", "twJoin", "tv", "cn"]
}
}
}
}
},
"javascript": {
"formatter": {
"quoteStyle": "double"
}
},
"css": {
"parser": {
"cssModules": true,
"allowWrongLineComments": true,
"tailwindDirectives": true
},
"formatter": {
"enabled": false
},
"linter": {
"enabled": false
}
},
"assist": {
"enabled": true,
"actions": {
"source": {
"organizeImports": "on"
}
}
}
}
npm scriptにlintとlint:fixを追加しておく –unsafeオプションはご自由に 僕はつけます
"scripts": {
"lint": "biome check",
"lint:fix" : "biome check --write --unsafe"
},
Vitest#
テストにはVitestを使う 正直そんなに使ったことない
pnpm add -D vitest
npm scriptにtestを追加する
"scripts": {
"test": "vitest"
},
Storybook#
AIと色々やるときにあるとすごい便利
ReactとかのUIライブラリが依存関係に入っていないと自動作成に失敗するみたいなので注意
pnpm create storybook@latest
あとは画面の指示に従うだけ
Tailwindcssの設定もしておく
https://pystyle.info/react-vite-tailwind-storybook/
Storycap#
ビジュアルリグレッションテストを簡単に行えるよう、コンポーネントのスクショを自動で取れるようにしておく
AIにUIコンポーネントを触らせるときにちょっとだけ安心できる
Storycapとあるが正確には改良版のStorycap-testrunというもの
pnpm add -D @storycap-testrun/browser
vitest.setup.tsに以下を追記
import { page } from "vitest/browser";
import { screenshot } from "@storycap-testrun/browser";
afterEach(async (context) => {
await screenshot(page, context);
});
vitest.config.tsのプラグインに以下を追記
import storycap from "@storycap-testrun/browser/vitest-plugin";
storycap({
output: {
file: (context) => `${context.id}.png`,
},
}),
.gitignoreに__screenshots__と書いておくと良い
Git/GitHubとCI/CD#
基本的にGit Flowをちょっと省略したブランチ戦略を取る
releaseブランチを省略(リリース作業は自動化、それ以外はdevelopでするので)
hotfixブランチも省略
Gitの設定#
やっていなければリポジトリの初期化 masterとmainに注意(n敗)
git init .
.gitignoreの設定
https://github.com/github/gitignore
こういうところから持ってくる
コミット前に自動修正#
lefthookとbiomeを組み合わせる
pnpm add -D -w lefthook
lefthook.yamlを作成する
pre-commit:
commands:
check:
glob: "*.{js,ts,cjs,mjs,d.cts,d.mts,jsx,tsx,json,jsonc}"
run: npx @biomejs/biome check --write --no-errors-on-unmatched --files-ignore-unknown=true --colors=off {staged_files}
stage_fixed: true
pre-push:
commands:
check:
glob: "*.{js,ts,cjs,mjs,d.cts,d.mts,jsx,tsx,json,jsonc}"
run: npx @biomejs/biome check --no-errors-on-unmatched --files-ignore-unknown=true --colors=off {push_files}
適用
pnpm lefthook install
GitHub#
とりあえずリポジトリを作る。masterとmainに注意 上でやった.gitignoreはここでやってもいい
Renovateとかを有効化しておく
設定していく
- オートマージを許可
- デフォルトブランチをdevelopに
- プルリクエストブランチの更新を常に提案する
- ヘッドブランチを自動的に削除する
- Dependabot Alertsを有効にする
- ブランチプロテクションルールを作成する CIの構築をしてからの方が楽
- Masterブランチは直Push禁止
- CI全Passが必須
- バイパス禁止
- Developブランチは直Push許可
- CI全Passが必要だがバイパスを許可
- レビューが必要なら最少Approve数を設定
- Masterブランチは直Push禁止
- チーム開発ならWebhookを設定
- Issue追加・PR追加・リリースあたりを通知してスレッド運用が良さげ 正直SlackのGitHub Appが一番いい
- Discord https://mekurun.com/tips/discord-github/
Renovate#
依存ライブラリのバージョン管理は自動化する
- minorとpatchの自動マージを有効化
- platformAutomergeを有効化
- rebaseWhenをconflictedかneverに
- lockFileMaintenanceをtrueに 正直いらんかも
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["config:recommended"],
"packageRules": [
{ "matchUpdateTypes": ["minor", "patch"], "automerge": true }
],
"platformAutomerge": true,
"rebaseWhen": "conflicted",
"lockFileMaintenance": {
"enabled": true,
"recreateWhen": "always",
"rebaseStalePrs": true,
"branchTopic": "lock-file-maintenance",
"commitMessageAction": "Lock file maintenance",
"commitMessageTopic": null,
"commitMessageExtra": null,
"schedule": ["before 4am on monday"],
"groupName": null,
"prBodyDefinitions": {
"Change": "All locks refreshed"
}
}
}
Vitest#
package.json内に存在している不要なtestスクリプトは削除しておく
ルートのpackage.jsonに
"test:all": "pnpm -r --reporter-hide-prefix test"
を追記しておく
-rオプションで子プロジェクトでも再起的に実行 –reporter-hide-prefixオプションで後述するテストレポートの邪魔を防げる
簡単にテストレポートを手に入れる手段としてGitHubのアノテーションを使う
https://vitest.dev/guide/reporters.html#github-actions-reporter
VRT(ビジュアルリグレッションテスト)#
AIにUIを触らせるならあったらすごく便利です
reg-viz/reg-actions@v3を使います。
playwrightとのインストールが必要な割に実行する必要があるタイミングが多く、コストが重め
PRのコメントに差分を投稿してくれるけど、PRのマージ先のコミットで必ずVRTが実行されている必要があるため、マージコミットにもVRTのアクションを実行する必要がある(この仕様にめちゃくちゃハマった)
残っている最新のスクショ結果ではなく、最新のコミットのスクショを探すという点に注意
簡単に書くのが凄く難しいので今動いているActionをそのまま書いておきます
@travel-scheduler/uiの部分をUIコンポーネントのパッケージ名に変えると動くと思います。
name: Visual Regression Test
on:
push:
branches: [develop, main]
pull_request:
branches: [develop, main]
permissions:
contents: write
actions: write
pull-requests: write
jobs:
test:
timeout-minutes: 10
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
shard: [1/3, 2/3, 3/3]
steps:
- uses: actions/checkout@v6
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v6
with:
node-version: 22
cache: "pnpm"
- name: Install dependencies
run: pnpm install
- name: Cache Playwright binaries
uses: actions/cache@v5
id: playwright-cache
with:
path: ~/.cache/ms-playwright
key: ${{ runner.os }}-playwright-${{ hashFiles('**/pnpm-lock.yaml') }}
- name: Install Playwright Browsers
if: steps.playwright-cache.outputs.cache-hit != 'true'
run: pnpm -F @travel-scheduler/ui exec playwright install chromium
- name: Install Playwright system dependencies
run: pnpm -F @travel-scheduler/ui exec playwright install-deps chromium
- name: Run storycap tests (shard ${{ matrix.shard }})
run: pnpm -F @travel-scheduler/ui exec vitest run --project=storybook --shard=${{ matrix.shard }}
- name: Upload screenshots
uses: actions/upload-artifact@v6
if: always()
with:
name: screenshots-${{ strategy.job-index }}
path: packages/ui/__screenshots__
retention-days: 1
compare:
needs: test
if: always()
timeout-minutes: 5
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Download all screenshot artifacts
uses: actions/download-artifact@v7
with:
pattern: screenshots-*
path: downloaded-screenshots
- name: Merge screenshots
run: |
mkdir -p packages/ui/__screenshots__
for dir in downloaded-screenshots/screenshots-*; do
if [ -d "$dir" ]; then
cp -r "$dir"/* packages/ui/__screenshots__/ 2>/dev/null || true
fi
done
echo "Merged screenshots:"
ls -la packages/ui/__screenshots__/
- name: Upload merged screenshots
uses: actions/upload-artifact@v6
with:
name: storycap-report
path: packages/ui/__screenshots__
retention-days: 30
- name: Run visual regression comparison
uses: reg-viz/reg-actions@v3
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
image-directory-path: "./packages/ui/__screenshots__"
Changesetsによるバージョン管理#
自分は調べながら初めて使ったけど、とても便利そう
インストール
pnpm add -wD @changesets/cli
初期化
npx changesets init
変更を追記(GitHub Appで自動化可能)
npx changesets
追記した変更をまとめてリリース(GitHub Actionで自動化可能)
npx changesets version
変更の追記の確認をしてくれるBot
https://github.com/apps/changeset-bot
masterにpushがあったら自動でリリース(changesets version)を行うAction
name: Release
on:
push:
branches:
- master
concurrency: ${{ github.workflow }}-${{ github.ref }}
jobs:
release:
name: Release
permissions:
pull-requests: write
contents: write
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@v3
- uses: pnpm/action-setup@v4
with:
run_install: false
- name: Setup Node.js 20
uses: actions/setup-node@v3
with:
node-version: 22
- name: Install Dependencies
run: pnpm install
- name: Create Release Pull Request
uses: changesets/action@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
npm versionによるバージョン管理#
npmではやったことないけど、Gradleでは近い方法でバージョン管理をしていた 全パッケージが同じバージョン番号を持つプロジェクトやモノレポじゃないプロジェクトではGitに全部を合わせることができるので楽
https://qiita.com/minamo173/items/8b8b27bc6ecd17ad925e
masterブランチにtagがpushされたときにfrom-gitで発動させる
GitHub Copilotによるレビューを行う#
自動でレビューさせるかはともかく設定する
https://github.com/settings/copilot/features
で有効化できる
.github/copilot-instructions.mdに日本語で頼む的な指示を書いておきましょう。
AI関連のことも書こうかと思ったけどだいぶ長い記事になったので一旦ここまで
