0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

バイブコーディングでReact / Express アプリつくーる

Last updated at Posted at 2025-12-08

はじめに

バイブコーディングでReact / Express アプリを作っていきます

開発環境

  • MacBook Air M1, 2020
  • Cursor 2.1.50
  • nvm 0.39.7
  • Node.js 22.4.0

フォルダ構成

frontend: Vite + React + TypeScript のフロントエンド
backend: Express + TypeScript のバックエンド

導入

💬 frontendフォルダに vite, react, ts アプリをセットアップして

cd frontend
npm create vite@latest . -- --template react-ts

> npx
> create-vite . --template react-ts

│
◇  Use rolldown-vite (Experimental)?:
│  No
│
◇  Install with npm and start now?
│  No
│
◇  Scaffolding project in /frontend...
│
└  Done. Now run:

  npm install
  npm run dev

フロントエンドの起動

npm install
npm run dev

localhost:5173にアクセス
20251208-025305-b649418a.png

💬 backendにexpress+tsのバックエンドAPIをセットアップして

backend/package.json
{
  "name": "backend",
  "version": "1.0.0",
  "description": "Express + TypeScript Backend API",
  "main": "dist/index.js",
  "type": "module",
  "scripts": {
    "dev": "tsx watch src/index.ts",
    "build": "tsc",
    "start": "node dist/index.js",
    "type-check": "tsc --noEmit"
  },
  "dependencies": {
    "express": "^4.18.2",
    "cors": "^2.8.5",
    "dotenv": "^16.3.1"
  },
  "devDependencies": {
    "@types/express": "^4.17.21",
    "@types/cors": "^2.8.17",
    "@types/node": "^20.10.0",
    "tsx": "^4.7.0",
    "typescript": "^5.3.3"
  }
}
backend/tsconfig.ts
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext",
    "lib": ["ES2022"],
    "moduleResolution": "node",
    "rootDir": "./src",
    "outDir": "./dist",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "resolveJsonModule": true,
    "declaration": true,
    "declarationMap": true,
    "sourceMap": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist"]
}
backend/src/index.ts
import express, { Request, Response } from 'express';
import cors from 'cors';
import dotenv from 'dotenv';

dotenv.config();

const app = express();
const PORT = process.env.PORT || 3001;

// ミドルウェア
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

// ルート
app.get('/', (req: Request, res: Response) => {
  res.json({ message: 'Express + TypeScript API is running!' });
});

app.get('/api/health', (req: Request, res: Response) => {
  res.json({ status: 'ok', timestamp: new Date().toISOString() });
});

// エラーハンドリング
app.use((err: Error, req: Request, res: Response, next: any) => {
  console.error(err.stack);
  res.status(500).json({ error: 'Something went wrong!' });
});

// 404ハンドリング
app.use((req: Request, res: Response) => {
  res.status(404).json({ error: 'Route not found' });
});

app.listen(PORT, () => {
  console.log(`Server is running on http://localhost:${PORT}`);
});
backend/.env
PORT=3001
NODE_ENV=development
backend/.gitignore
node_modules/
dist/
.env
*.log
.DS_Store
cd backend
npm install
npm run dev

http://localhost:3001 にアクセス
20251208-063452-1e4576f8.png

http://localhost:3001/api/health にアクセス
image.png

💬 フロントエンドでこのhealth APIを実行するだけのページにして

1.frontend/src/App.tsx - health APIを呼び出すページ
2.frontend/vite.config.ts - プロキシ設定(オプション)

20251208-064548-6ae92f52.png

image.png

💬 Basic認証を追加して
1.バックエンドの変更 (backend/src/index.ts)
2.フロントエンドの変更 (frontend/src/App.tsx)

💬 ログインページを追加して
frontend/src/App.tsx - ログイン機能を追加

image.png

💬 ユーザー名とパスワードを間違えた時に、ポップアップのログインが表示されてしまってるよ
Attached_image.png

💬 ヘッダーを追加して、ログアウトボタンを右上に移動して
20251208-082621-8a489880.png

💬 全然ダメですね。モダンなダッシュボードにして下さい。
image.png

image.png

💬 ページ幅を100%使うようにして @frontend/src/App.css @frontend/src/App.tsx @frontend/src/index.css

20251208-090931-7550052f.png

20251208-091009-6fbc4fa8.png

💬 認証周りのセキュリティは大丈夫かな?

1. localStorageにパスワードを保存しない(セッショントークンやJWTのみ保存)
2. 環境変数が必須になるようバリデーションを追加
3. HTTPSを必須化、またはJWT/Session認証へ移行
4. CORSを適切に制限(特定のオリジンのみ許可)
5. X-Requested-Withに依存しない実装に変更
6. 本番環境では詳細なエラー情報を返さない

💬 JWTトークンを使用するように変更して
1.バックエンドにjsonwebtokenパッケージを追加
2.バックエンドの認証ロジックをJWTに変更(ログインエンドポイント追加、認証ミドルウェア変更)
3.フロントエンドをJWTトークンを使用するように変更(パスワード保存を削除、トークンのみ保存)

💬 フロントエンドとバックエンドの起動方法をREADMEに書いて

# my-react-express-ngrok

React + Express + TypeScript のフルスタックアプリケーション

## プロジェクト構成

```
my-react-express-ngrok/
├── frontend/     # React + TypeScript + Vite
└── backend/      # Express + TypeScript
```

## セットアップ

### バックエンドのセットアップ

1. バックエンドディレクトリに移動
```bash
cd backend
```

2. 依存関係をインストール
```bash
npm install
```

3. 環境変数ファイルを作成(オプション)
```bash
# .env ファイルを作成
PORT=3001
AUTH_USERNAME=admin
AUTH_PASSWORD=password
JWT_SECRET=your-secret-key-change-in-production
JWT_EXPIRES_IN=24h
```

デフォルト値:
- PORT: 3001
- AUTH_USERNAME: admin
- AUTH_PASSWORD: password
- JWT_SECRET: your-secret-key-change-in-production(本番環境では必ず変更してください)
- JWT_EXPIRES_IN: 24h

**重要**: 本番環境では以下の環境変数が必須です:
- `JWT_SECRET`: 強力な秘密鍵を設定してください
- `AUTH_USERNAME`: 認証用のユーザー名
- `AUTH_PASSWORD`: 認証用のパスワード

### フロントエンドのセットアップ

1. フロントエンドディレクトリに移動
```bash
cd frontend
```

2. 依存関係をインストール
```bash
npm install
```

## 起動方法

### バックエンドの起動

1. バックエンドディレクトリに移動
```bash
cd backend
```

2. 開発サーバーを起動
```bash
npm run dev
```

バックエンドAPIは `http://localhost:3001` で起動します。

### フロントエンドの起動

1. フロントエンドディレクトリに移動
```bash
cd frontend
```

2. 開発サーバーを起動
```bash
npm run dev
```

フロントエンドは `http://localhost:5173` で起動します。

## 使用方法

1. バックエンドとフロントエンドの両方を起動します
2. ブラウザで `http://localhost:5173` にアクセスします
3. ログインページで認証情報を入力します
   - デフォルトのユーザー名: `admin`
   - デフォルトのパスワード: `password`
4. ログイン成功後、JWTトークンが発行され、localStorageに保存されます
5. ログイン後、ダッシュボードからHealth APIをチェックできます

## 認証について

このアプリケーションはJWT(JSON Web Token)認証を使用しています。

### 認証フロー

1. ユーザーがログイン情報を入力
2. バックエンドの `/api/login` エンドポイントにPOSTリクエストを送信
3. 認証成功後、JWTトークンが発行される
4. トークンはフロントエンドのlocalStorageに保存される(パスワードは保存されません)
5. 以降のAPIリクエストでは、`Authorization: Bearer <token>` ヘッダーでトークンを送信
6. バックエンドでトークンを検証し、有効な場合のみリクエストを処理

### セキュリティ機能

- ✅ パスワードはlocalStorageに保存されません
- ✅ JWTトークンには有効期限が設定されています(デフォルト: 24時間)
- ✅ トークンは署名済みで、改ざんを検知できます
- ✅ 本番環境では環境変数の設定が必須です

## ビルド

### バックエンドのビルド

```bash
cd backend
npm run build
```

ビルド後のファイルは `dist/` ディレクトリに生成されます。

### フロントエンドのビルド

```bash
cd frontend
npm run build
```

ビルド後のファイルは `dist/` ディレクトリに生成されます。

## 技術スタック

### フロントエンド
- React 19
- TypeScript
- Vite
- CSS (Inline Styles)

### バックエンド
- Express
- TypeScript
- JWT認証(jsonwebtoken)
- CORS対応
- dotenv(環境変数管理)

## API エンドポイント

### 公開エンドポイント

- `GET /` - APIの状態確認
- `POST /api/login` - ログイン(JWTトークンを発行)

### 保護されたエンドポイント

- `GET /api/health` - ヘルスチェック(認証必須)

保護されたエンドポイントには、`Authorization: Bearer <token>` ヘッダーが必要です。

クローンした人がすぐに始められるよう、環境変数の例(.env.example)を追加しておきましょう。

backend/.env.example
PORT=3001
AUTH_USERNAME=admin
AUTH_PASSWORD=password
JWT_SECRET=your-secret-key-change-in-production
JWT_EXPIRES_IN=24h

お疲れ様でした。

リポジトリはこちら


ngrokで外部に公開する方法

※新規アカウントでエンドポイントが2つ作成されなかったのでできないかも

ngrokのインストール

brew install ngrok

ngrokのauthtokenを設定

ngrok config add-authtoken YOUR_AUTHTOKEN

ngrok.ymlファイルの作成

ngrok.yml
version: 3

agent:
  authtoken: your_authtoken

tunnels:
  frontend:
    addr: 5173
    proto: http
  backend:
    addr: 3001
    proto: http

ルートに.gitignoreを作成

.DS_Store
ngrok.yml

フロントエンドの環境変数設定(frontend/.env)

frontend/.env.example
VITE_API_BASE_URL=your-ngrok-backend-url

.gitignoreの末尾に.envを追加

frontend/.gitignore
.env

フロントエンドコードの修正(App.tsx)
App.tsxの修正: 環境変数 VITE_API_BASE_URL を使用するように変更

vite.config.tsの修正

vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

// https://vite.dev/config/
export default defineConfig({
  plugins: [react()],
  server: {
    allowedHosts: [
      '.ngrok-free.app',
      '.ngrok.app',
      'localhost'
    ],
    proxy: {
      '/api': {
        target: 'http://localhost:3001',
        changeOrigin: true,
      }
    }
  }
})

ngrokを起動

ngrok start --all --config ngrok.yml
Forwarding    https://xxxxxxxxxxxx.ngrok-free.app -> http://localhost:5173
Forwarding    https://yyyyyyyyyyyy.ngrok-free.app -> http://localhost:3001

バックエンドの起動

cd backend
npm run dev

フロントエンドの.envのVITE_API_BASE_URLをngrokのバックエンドのURLに変更

VITE_API_BASE_URL=https://yyyyyyyyyyyy.ngrok-free.app

フロントエンドの起動

cd frontend
npm run dev

https://xxxxxxxxxxxx.ngrok-free.app にアクセス


プロジェクトは通常のクライアントサイドReactアプリのため、脆弱性CVE-2025-55182(React2Shell)の影響は受けませんが、セキュリティのベストプラクティスとして修正しました。

frontend/package.json
  "dependencies": {
    "react": "^19.2.1",
    "react-dom": "^19.2.1"
  },
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?