【Cursor実践】jQueryをTypeScript/Reactへ!AIと挑むレガシーコード近代化戦略
「数年前に書かれた1,000行超えのjQueryコードを、明日までにReact + TypeScriptへ移行してほしい」
開発現場でこんな無理難題を突きつけられ、途方に暮れた経験はありませんか? 仕様書は存在せず、イベントハンドラが複雑に絡み合い、グローバル変数が飛び交うレガシーコード。手動で解析して書き直すにはあまりにもリスクが高く、膨大な時間が奪われていきます。
しかし、安心してください。次世代AIアシストエディタ「Cursor」を正しく使いこなせば、この絶望的なレガシーコード移行プロジェクトは「最高にエキサイティングで安全なモダナイゼーション」へと変貌します。
この記事では、単なるAIの使い方にとどまらず、設計方針を維持しながらバグを1つも出さずにレガシーJS(jQuery)をモダンなReact/TypeScript環境へ移行する極意を、親身な先輩エンジニアの視点から徹底解説します!
—
1. なぜ「レガシー移行」にCursorが圧倒的に最強なのか?
一般的なWebチャット型AI(ChatGPTなど)にコードを貼り付けて移行しようとすると、以下のような限界にぶち当たります。
- ファイル単位のコンテキストしか理解できない(他ファイルの型定義やユーティリティ関数を無視する)
- ドメインロジックの「隠れた仕様」を見落とし、勝手に機能を削ってしまう
- 出力結果をプロジェクトに書き戻すコピペ作業でミスが発生する
Cursorは違います。CursorはVS Codeをベースに開発され、プロジェクト全体のコードベースをバックグラウンドでインデックス化(ベクトル化)しています。
[レガシープロジェクト全体]
│
▼ (バックグラウンド自動インデックス作成)
[Vector Embedding DB] ─── (関連コードを自動検索) ───┐
▼
[ユーザーのプロンプト] ───────────────────────────► [Cursor AI Engine]
│
▼
[高精度なモダナイズコード出力]
エディタ自身がプロジェクトの構造、共通ライブラリ、依存関係を深く理解しているため、「このjQueryのイベント発火、実は別ファイルのこのグローバル変数に依存しているな」といった隠れた設計意図を汲み取った上でモダナイズを実行できるのです。
—
2. 準備編:移行精度を10倍に引き上げる環境セットアップ
まずはCursorをインストールし、レガシー移行に特化した「脳」をCursorにセットしましょう。インストール自体は公式サイトからアプリをダウンロードしてインストールするだけですが、真の勝負はセットアップにあります。
ステップ1: コードベースのインデックス作成を確認
Cursorを開いたら、まずはプロジェクト全体をAIに学習させます。
1. `Settings` (画面右上の歯車マークまたは `Cmd/Ctrl + ,`) を開きます。
2. `Features` > `Codebase Indexing` を確認します。
3. `Index new folder` が有効になっており、ステータスが 100% Indexed になっていることを確認してください。
これだけで、Cursorはあなたのレガシーコードの全貌を把握しました。
ステップ2: 移行プロジェクト専用の `.cursorrules` を配置する
ここがプロと素人を分ける最も重要な設定です。プロジェクトのルートディレクトリに `.cursorrules` というファイルを作成し、AIに対する「厳格な移行ルール」を定義します。
以下のコードをそのままコピーして `.cursorrules` として保存してください。
{
“instruction”: “あなたは熟練したフロントエンドアーキテクトです。レガシーなJavaScript/jQueryコードを、堅牢で保守性の高いReact + TypeScriptコードへリファクタリングする任務を担っています。”,
“rules”: [
“1. コンポーネント化する際は、単一責任の原則(SRP)を厳格に守ってください。”,
“2. any型は絶対に使用禁止です。不明な型は仮のinterfaceを定義し、TODOコメントを残してください。”,
“3. jQueryのDOM操作($.ajax, $(‘#id’).html()等)は、ReactのState, Effect, またはカスタムHookに完全に置き換えてください。”,
“4. 既存のビジネスロジックや例外処理、エッジケースの挙動を破壊しないでください。”,
“5. 変換後のコードには、どのレガシーコードに対応しているかを示す丁寧なJSDocコメントを付与してください。”
]
}
このルールを書いておくことで、AIがありがちな「適当な`any`型で済ませる」「勝手に例外処理を消す」といった暴走を劇的に防ぐことができます。
—
3. 実践:jQueryスパゲティを「React + TypeScript」へ書き換える(Hello World)
では、具体的なコードを使って移行プロセスを試してみましょう!
ターゲットとなる「レガシーjQueryコード」
以下のような、典型的な「APIからユーザー一覧を取得してテーブルに描画し、ローディング状態を制御する」jQueryコード(`legacyUserList.js`)があるとします。
// legacyUserList.js
$(document).ready(function() {
var $loading = $(‘#loading-spinner’);
var $tableBody = $(‘#user-table-body’);
function fetchUsers() {
$loading.show();
$.ajax({
url: ‘/api/v1/users’,
method: ‘GET’,
success: function(response) {
$loading.hide();
$tableBody.empty();
// DOMの直接構築(スパゲティ化の原因)
$.each(response.data, function(index, user) {
var row = ‘
‘
‘ +
‘
‘ +
‘
‘ +
‘
‘;
$tableBody.append(row);
});
},
error: function(err) {
$loading.hide();
alert(‘ユーザー情報の取得に失敗しました’);
}
});
}
// 初期化実行
fetchUsers();
});
このコードは、HTMLのDOM構造に強く依存し、型も存在せず、エラーハンドリングも`alert`という非常に見通しの悪い状態です。
—
Cursorの「Composer」機能で一括モダナイズ
Cursorの最新機能 Composer (`Cmd + I` または `Ctrl + I`) を起動します。Composerは複数のファイルを横断して修正・生成ができる最強のAIミドルウェアです。
Composerの入力欄に、次のようにプロンプトを入力します。
@legacyUserList.js をリファクタリングしてください。
【要件】
1. このjQueryコードからビジネスロジックを抽出したカスタムHook `useFetchUsers.ts` を作成してください。
2. 取得したデータを安全に扱うための TypeScript インターフェース `User` を定義してください。
3. 表示層として React Functional Component `UserTable.tsx` を作成してください(Tailwind CSSを使用)。
4. `.cursorrules` の規定に厳格に従ってください。
—
生成されるモダナイズコード
Cursorはプロンプトと `.cursorrules` を読み込み、一瞬で以下のような完璧に分離されたモダンコードを生成します!
1. 型定義 (`types/user.ts`)
/
- ユーザー情報の型定義
- レガシーAPI (/api/v1/users) のレスポンス構造に基づく
/
export interface User {
id: number;
name: string;
isAdmin: boolean;
}
export interface ApiResponse
data: T;
message?: string;
}
2. カスタムHook (`hooks/useFetchUsers.ts`)
import { useState, useEffect } from ‘react’;
import { User, ApiResponse } from ‘../types/user’;
export const useFetchUsers = () => {
const [users, setUsers] = useState
const [loading, setLoading] = useState
const [error, setError] = useState
useEffect(() => {
const fetchUsers = async () => {
setLoading(true);
setError(null);
try {
const response = await fetch(‘/api/v1/users’);
if (!response.ok) {
throw new Error(‘ネットワークレスポンスが正常ではありませんでした’);
}
const data: ApiResponse
setUsers(data.data);
} catch (err) {
const errorMessage = err instanceof Error ? err.message : ‘予期せぬエラーが発生しました’;
setError(errorMessage);
} finally {
setLoading(false);
}
};
fetchUsers();
}, []);
return { users, loading, error };
};
3. Reactコンポーネント (`components/UserTable.tsx`)
import React from ‘react’;
import { useFetchUsers } from ‘../hooks/useFetchUsers’;
/
- ユーザー一覧表示コンポーネント
- legacyUserList.js のDOM描画処理を宣言的UIへ移行
/
export const UserTable: React.FC = () => {
const { users, loading, error } = useFetchUsers();
if (loading) {
return (
読み込み中…
);
}
if (error) {
return (
エラーが発生しました
{error}
);
}
return (
| ID | 名前 | 権限 |
|---|---|---|
| {user.id} | {user.name} |
{user.isAdmin ? ‘管理者’ : ‘一般’} |
);
};
手動でやれば型定義、Hook抽出、エラーハンドリングの書き直し、CSSフレームワークの適用など最低でも2〜3時間はかかる作業が、わずか30秒で完結しました。
—
4. バグをゼロにするための「検証プロンプト」とテスト自動化
コードが生成されて「はい終わり!」とするのは時期尚早です。AIモダナイゼーションで最も恐ろしいのは、見た目は綺麗だが「元のコードにあった細かい仕様(エッジケース)」が抜け落ちることです。
バグを完全にシャットアウトするために、以下の検証プロセスを必ず実行しましょう。
プロセス1: 型チェックコマンドの実行ログをCursorに食わせる
端末(Terminal)でTypeScriptの型チェックを実行します。
型エラーのみをチェック(JavaScriptファイルを生成しない)
npx tsc –noEmit
もし以下のようなエラーログが出力されたとします。
src/hooks/useFetchUsers.ts:15:21 – error TS2339: Property ‘data’ does not exist on type ‘User[]’.
このエラーログを丸ごとコピーし、CursorのChat (`Cmd + L`) に次のように投げます。
> プロンプト:
> `npx tsc –noEmit` を実行したところ、以下の型エラーが発生しました。修正してください。
> [エラーログを貼り付け]
Cursorは即座にレスポンス構造の型の不整合(配列とオブジェクトのラップ構造の差異)を見抜き、修正コードを提案してくれます。
プロセス2: 振る舞い同等性を保証する「Jestテスト」の自動作成
レガシーコードと新コードで「動的に仕様が変わっていないか」を担保するため、Cursorにテストコードを書かせます。
> プロンプt例:
> `UserTable.tsx` と `useFetchUsers.ts` に対する Jest + React Testing Library のユニットテストコードを作成してください。
> APIモック(MSWまたはjest.fn)を使用し、①正常系でのデータ描画、②ローディング状態、③エラー発生時の表示 の3パターンを網羅してください。
生成されたテストを実行し、すべてグリーン(成功)になることを確認する。これが「絶対に破壊しないレガシー移行」の鉄則です。
—
5. まとめ:Cursorはエンジニアの価値を最高に高めるパートナー
今回の記事では、レガシーなjQueryコードをCursorを使って安全かつ高速にReact + TypeScript環境へモダナイズする戦略をお伝えしました。
1. `.cursorrules` で厳格な移行ルールを定義する
2. Composer (`Cmd + I`) で設計意図(型・Hook・UI)を分離して生成させる
3. `tsc –noEmit` と自動生成テストで振る舞いの同等性を完全に検証する
この手順をマスターすれば、これまでチーム全員が嫌がっていた「レガシーコードの保守・移行タスク」が、あなたにとって最も成果を出しやすく、圧倒的に感謝されるアピールチャンスに変わります!
AIは私たちの仕事を奪うものではなく、退屈で危険な単純作業を引き受け、「本来注力すべきシステム設計や価値創造」に集中させてくれる最強の相棒です。
ぜひ今日から、手元のレガシープロジェクトでCursorの真価を体感してみてください。毎日のコーディングが驚くほど軽やかで、楽しくなるはずですよ!