こんにちは!フロントエンドの開発現場で、こんなストレスを抱えたことはありませんか?
「画面のレイアウトは組めたのに、肝心のバックエンドAPIがまだ実装されていなくて動けない……」
「ちょっとしたログイン後の挙動を確認したいだけなのに、大掛かりな認証基盤やモックサーバーを立ち上げるのが面倒……」
大規模な開発になればなるほど、チーム間の依存関係や環境構築の重さに足を取られがちです。しかし、あなたが普段使っているモダンなビルドツール「Vite(ビイト)」には、そんな停滞を一瞬で吹き飛ばす秘密兵器が備わっています。それが今回紹介する `configureServer`(カスタムミドルウェア) です。
この記事をマスターすれば、外部のAPIサーバーが完成していなくても、あなたのブラウザとViteのローカル開発サーバーだけで完璧なAPIスタブや認証フローを完結させられるようになります。毎日のコーディングが劇的にスムーズになる魔法のようなテクニック、一緒に見ていきましょう!
—
そもそも「Viteのカスタムミドルウェア」って何をするもの?
Viteは単なる「超高速なビルドツール」だと思っていませんか? 実はその内部で、Node.jsベースの強力な開発用HTTPサーバー(Connectベース)を動かしています。
通常、Viteは「ブラウザからのリクエストを受け取る $\rightarrow$ ソースコードをその場でトランスパイルして返す」という役割を担っています。しかし、このサーバーに対して「特定のURLにリクエストが来たら、ファイルシステムからJSONを返したり、簡易的なセッション状態を記憶したりする」という独自の割り込み処理(ミドルウェア)を差し込むことができるのです。
これの何が嬉しいかと言うと、わざわざJSON Serverなどの外部ツールを別ポートで立ち上げる必要がなくなる点です。フロントエンドのコードと同じリポジトリ、同じViteのプロセス内で完結するため、CORS(Cross-Origin Resource Sharing)の面倒な設定に悩まされることも一切なくなります。
—
最速で体感する!カスタムミドルウェアの基本セットアップ
百聞は一見にしかず。実際に手を動かして、Viteのミドルウェアがどう動くのかを体験してみましょう。
1. プロジェクトの作成とViteの導入
まずは、モダンなVite環境をサクッと立ち上げます。Node.jsがインストールされている環境で、ターミナルを開いて以下のコマンドを実行してください。
対話形式でプロジェクトを作成します
プロジェクト名: vite-middleware-lab
フレームワーク: Vanilla または React (今回は純粋な仕組みを知るためにVanillaを選択すると分かりやすいです)
バリアント: TypeScript または JavaScript
npm create vite@latest vite-middleware-lab — –template vanilla-ts
作成したディレクトリへ移動
cd vite-middleware-lab
依存パッケージをインストール
npm install
2. `vite.config.ts` でサーバーの挙動をハックする
ここが今回の核心です。Viteの設定ファイルである `vite.config.ts` を開き、`configureServer` フックを使ってミドルウェアを追加します。
以下のコードに書き換えてみてください。
import { defineConfig } from ‘vite’;
export default defineConfig({
// 開発サーバーの設定を行います
server: {
port: 3000, // 開発サーバーのポートを3000に固定
},
// Viteの内部サーバーにカスタム処理を組み込むプラグイン定義
plugins: [
{
name: ‘configure-server-middleware’,
configureServer(server) {
// server.middlewares.use() で、リクエストをフックするミドルウェアを追加します
server.middlewares.use((req, res, next) => {
// 1. /api/todos というURLへのGETリクエストをインターセプト(横取り)する
if (req.url === ‘/api/todos’ && req.method === ‘GET’) {
// レスポンスのヘッダーに「JSONを返す」ことを明記
res.setHeader(‘Content-Type’, ‘application/json’);
res.statusCode = 200;
// 返却するモックデータ(バックエンドの代わり)
const mockTodos = [
{ id: 1, title: ‘Viteのカスタムミドルウェアを極める’, completed: true },
{ id: 2, title: ‘バックエンドの完成を待たずにUI開発を進める’, completed: false },
{ id: 3, title: ‘快適なローカル開発環境に酔いしれる’, completed: false }
];
// JSON文字列に変換してブラウザに返す
res.end(JSON.stringify(mockTodos));
return; // 処理をここで終了し、通常のViteの処理に進ませない
}
// 条件に一致しない通常のリクエストは、次の処理(Vite本来のファイル配信など)へ流す
next();
});
}
}
]
});
【アーキテクトの解説:ここで何が起きているのか?】
ブラウザから `/api/todos` にアクセスがあった瞬間、Viteはこのカスタムミドルウェアによってリクエストをキャッチします。そして、データベースや外部APIを一切叩くことなく、コード内にハードコードされた `mockTodos` を瞬時にJSONとして返却します。`next()` を呼ばないことで、Viteに「このリクエストは私が処理したから、もう何もしなくていいよ」と伝えているわけです。
—
精度高い動作確認:Hello Worldを超えた「実用モック」の検証
それでは、実際にこのミドルウェアが正しく動くかブラウザから叩いて確認してみましょう。
1. 開発サーバーの起動
ターミナルで以下のコマンドを実行し、Viteを立ち上げます。
npm run dev
コンソールに `http://localhost:3000/` が表示されたら成功です。
2. フロントエンドからAPIを叩いてみる
プロジェクト内の `src/main.ts` (または `src/main.js`)を開き、先ほど作成したミドルウェア(API)をfetchで取得するコードを記述します。
import ‘./style.css’
document.querySelector
Vite Middleware Lab
`
// ボタンをクリックしたときにカスタムミドルウェアへリクエストを飛ばす
const button = document.querySelector(‘#fetch-btn’);
const todoList = document.querySelector(‘#todo-list’);
button?.addEventListener(‘click’, async () => {
try {
// まだ存在しないバックエンドの代わりに、Viteのミドルウェアが応答する
const response = await fetch(‘/api/todos’);
const todos = await response.json();
// 取得したデータを画面のリストに描画
if (todoList) {
todoList.innerHTML = todos.map((todo: any) => `
`).join(”);
}
} catch (error) {
console.error(‘API通信エラー:’, error);
}
});
ブラウザで `http://localhost:3000` を開き、「TODOリストをAPIから取得する」ボタンを押してみてください。
画面に、バックエンドサーバーを1行も立ち上げていないにもかかわらず、JSONデータが美しく描画されたはずです!
—
実践応用:認証フローとセッション状態をフロントエンドだけで完結させる
ここからが本番です。単なる静的なJSONを返すだけでなく、「簡易的なログイン状態(セッション)を保持するログイン・ログアウトのシミュレーション」をミドルウェア内に組み込んでみましょう。
実際の開発では、「ログインしている状態の画面」「ゲスト状態の画面」を行ったり来たりする検証が頻発します。これをミドルウェアのメモリ上に状態(State)を持たせることで、完全に再現できます。
`vite.config.ts` を以下のように拡張してみましょう。
import { defineConfig } from ‘vite’;
export default defineConfig(() => {
// サーバーのメモリ上に保持する簡易的なセッション状態
let isAuthenticated = false;
let currentUser = { name: ‘ゲストユーザー’, role: ‘guest’ };
return {
server: { port: 3000 },
plugins: [
{
name: ‘auth-simulation-middleware’,
configureServer(server) {
server.middlewares.use(async (req, res, next) => {
// 1. ログイン状態を確認するエンドポイント
if (req.url === ‘/api/auth/me’ && req.method === ‘GET’) {
res.setHeader(‘Content-Type’, ‘application/json’);
res.statusCode = 200;
res.end(JSON.stringify({ isAuthenticated, user: currentUser }));
return;
}
// 2. ログイン処理を行うエンドポイント
if (req.url === ‘/api/auth/login’ && req.method === ‘POST’) {
isAuthenticated = true;
currentUser = { name: ‘シニア開発者’, role: ‘admin’ };
res.setHeader(‘Content-Type’, ‘application/json’);
res.statusCode = 200;
res.end(JSON.stringify({ success: true, user: currentUser }));
return;
}
// 3. ログアウト処理を行うエンドポイント
if (req.url === ‘/api/auth/logout’ && req.method === ‘POST’) {
isAuthenticated = false;
currentUser = { name: ‘ゲストユーザー’, role: ‘guest’ };
res.setHeader(‘Content-Type’, ‘application/json’);
res.statusCode = 200;
res.end(JSON.stringify({ success: true }));
return;
}
next();
});
}
}
]
};
});
なぜこれが実務で神がかっているのか?
このアプローチの最大の美しさは、「Node.jsのメモリ空間(クロージャ変数)をそのままモックのデータストアとして利用できる」点です。
ブラウザをリロードしても、サーバーが生きている限りログイン状態が維持されます。本物のバックエンドが出来上がったあとも、APIののエンドポイント(URLパス)さえ合わせれば、フロントエンドのコードを一切書き換えることなく、そのまま本番用APIへ移行できます。
—
先輩エンジニアからのアドバイス:さらに開発を加速させるコツ
ここまでViteのカスタムミドルウェアの魅力をお伝えしてきましたが、プロジェクトが大きくなってきたときは以下の点に少しだけ気をつけてみてください。
1. ミドルウェアのファイルを分離する
`vite.config.ts` の中にすべてのモックロジックを書き下ろしていくと、設定ファイルが肥大化します。`src/mocks/middleware.ts` のように別ファイルに切り出し、それを `vite.config.ts` から読み込む形にすると、コードが美しく保てます。
2. 実ファイル(JSON)の読み込みと組み合わせる
コード内にハードコードするだけでなく、Node.jsの `fs` モジュールを使って `src/mocks/data/todos.json` などのファイルを読み込んで動的に返すようにすると、モックデータの管理がさらに楽になりますよ。
バックエンドの完成をただ待つだけの開発スタイルは、今日で終わりにしましょう。Viteのミドルウェアをハックして、自分の手で開発の主導権を完全に握り、フロントエンド開発を最高にスピーディーで楽しいものにしてください!