-
Notifications
You must be signed in to change notification settings - Fork 0
MS_ESProj
- 戻る(ASP.NET SPA、ASP.NET Core)
- Web Essentials
- ASP.NET Core SPAテンプレート
- .esproj(JavaScript・TypeScriptプロジェクトシステム)
- Visual Studio 2022 から本格導入された、モダンな SPA 開発を C# の世界(MSBuild)と
スマートに融合させるための新しいプロジェクト形式 - 従来のように「.csproj の中に無理やり JavaScript のファイルを詰め込む」のではなく、
フロントエンドを独立して扱うために作られた。
補足(何が「新しい」のか): 一連の SPA テンプレートの歴史
(ASP.NET Core SPAテンプレート、
JavaScript Services)の到達点が
.esprojである、と位置付けると分かりやすい。【第 1 世代(2017)】 JavaScript Services 1 つの .csproj に ClientApp フォルダを同居させる .NET が webpack を起動し、Node.js を子プロセスで抱える → 【.NET がフロントの面倒を見る】 → 廃止された ★ 【第 2 世代(2020 頃)】 手作業での分離 フロントを別フォルダ/別リポジトリにする それぞれ別に起動、別にビルド → 正しいが【IDE の支援がない】(VS の恩恵が薄い) 【第 3 世代(VS2022)】 .esproj フロントを【独立したプロジェクト】として扱う ただし【ソリューションには載る】 → 分離しつつ、IDE の統合(F5 で両方起動)は保つ ★「分離するが、統合された体験は諦めない」——
これが.esprojの設計思想である。
...VSCode 使えば良いのでは?...
補足(原文のこの一言への回答): 「VS Code 使えば良いのでは?」
という率直な疑問は、実務的にはかなり的を射ている。
公平に整理しておく。
観点 VS + .esproj VS Code(2 つ開く / 1 つで両方) C# のデバッグ 強力(VS の本領) 可能(C# Dev Kit)。VS には及ばない フロントの編集体験 普通 快適(拡張が豊富、動作が軽い) 起動(F5) 1 ボタンで両方 ★ launch.jsonの compound で同等にできるCI との一貫性 MSBuild に乗る npm scripts で明示的に書く チームの分業 フロント担当も VS が要る フロント担当は VS Code だけでよい ★ ライセンス VS のライセンスが要る 無償 動作の軽さ 重い 軽い 【.esproj が向く場面】 ・C# 開発者が【フロントも自分で書く】小~中規模チーム ・すでに VS ライセンスがあり、CI も MSBuild 中心 ・「F5 一発」の体験を重視する 【VS Code(分離)が向く場面】 ・フロント専任がいる(その人に VS を買う理由がない)★ ・フロントを別リポジトリ・別デプロイにする ・Mac / Linux の開発者がいる ・フロントのビルドを CI で独立させたい原文の疑問が妥当なのは、「.esproj でなければできないこと」が
ほとんどないためである。
.esprojが提供するのは利便性であって、機能ではない。ただし、「CI/CD を一本化できる」点は実質的な利点である
(後述の「どんな人に向いている?」)。
VS は VSC と同様に、生の npm、npx、または yarn、pnpm などの CLI ツールを
バックグラウンドで直接呼び出す。
補足(この点が最も重要):
.esprojは独自のビルド機構を持たない——
これが Web Essentials の失敗(= IDE 依存のコンパイラ)から
学んだ点である。【Web Essentials(2010~2015)】 VS の拡張機能が【自前で】LESS/Sass/TS をコンパイルしていた → VS がないとビルドできない ✗ 【.esproj(2022~)】 VS は【npm run build を呼ぶだけ】★ → package.json さえあれば、VS がなくてもビルドできる → CI でも、VS Code でも、コマンドラインでも同じ結果つまり、
.esprojを入れても
「VS がないとビルドできない」状態にはならない。
これは採用判断において重要な性質である。# .esproj のプロジェクトも、これで普通にビルドできる cd myapp.client npm ci npm run build
.esproj の導入により、Visual Studio での Web 開発は以下のように劇的に変化
-
ビルド
- ...が重い:C# をビルドするたびに npm run build が走り、時間がかかる。
- ...の分離:デバッグ時は Vite 等の高速な HMR(Hot Module Replacement)を使い、
C# 側は API のコンパイルだけに専念。
-
PJ 依存関係
- ...がごちゃ混ぜ:NuGet パッケージと npm パッケージの管理が 1 つの場所で混ざる。
- ...の完全分離:バックエンドは .csproj(NuGet)、
フロントエンドは .esproj(npm)と完全に分かれる。
-
デバッグの
- ...開始が面倒:API と SPA を両方立ち上げるために、
手動でターミナルを 2 つ開く必要があった。 - ...マルチスタートアップ:VS の「開始」ボタン 1 つで、
API の起動と SPA の開発サーバー(Vite 等)の起動、ブラウザ起動まで自動化。
- ...開始が面倒:API と SPA を両方立ち上げるために、
補足(3 つの課題の背景): それぞれ、旧テンプレートで実際に
起きていた問題である。① ビルドが重い
【旧(1 プロジェクト)】 dotnet build └ MSBuild のターゲットで npm run build が起動 └ webpack が全部バンドル(数十秒) → C# を 1 行直すだけでも、フロントが丸ごと再ビルドされる ★ 【新(.esproj)】 Debug 構成では ShouldRunBuildScript = false → npm run build を【走らせない】 → 代わりに Vite の dev server が HMR で差分更新② 依存関係のごちゃ混ぜ
【旧】 1 つのフォルダに MyApp.csproj(NuGet の参照) package.json(npm の依存) node_modules/(数万ファイル)★ ・node_modules が .csproj のファイル列挙に引っかかる → VS が遅くなる、ビルド対象に紛れ込む ・.gitignore の管理が煩雑 ・「このプロジェクトの依存は何か」が一目で分からない③ デバッグ開始が面倒
【旧(手動分離した場合)】 ターミナル1: dotnet run ターミナル2: npm run dev ブラウザ: 手で開く → 毎回この手順。新メンバーへの説明も要る 【新】 F5 一発なお、②の「完全分離」は現在の設計として正しいが、
node_modulesの重さは消えていない点に注意する。・node_modules は依然として巨大(数百 MB、数万ファイル) ・ウイルス対策ソフトの除外設定を推奨 → [ウイルススキャン] 参照 ・CI では npm ci(キャッシュ利用)で時間を抑える ・pnpm を使うと【ディスク使用量が劇的に減る】(ハードリンク方式)★
.esproj ファイルの実体は、C# の .csproj などと同じ XML 形式(MSBuild 形式)のファイルで、
主に「JavaScript ツールチェーンと MSBuild を結びつける設定」だけが書かれる。
<Project Sdk="Microsoft.VisualStudio.JavaScript.Sdk/1.0.0-alpha.x.x">
<PropertyGroup>
<StartupCommand>npm run dev</StartupCommand>
<JavaScriptTestRoot>src\</JavaScriptTestRoot>
<JavaScriptTestFramework>Jest</JavaScriptTestFramework>
<SpawnServerScript >true</SpawnServerScript>
<BuildOutputFolder>$(MSBuildProjectDirectory)\dist</BuildOutputFolder>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
<ShouldRunBuildScript>false</ShouldRunBuildScript>
</PropertyGroup>
<ItemGroup>
<Folder Include="src\assets\" />
</ItemGroup>
</Project>- 重要な MSBuild プロパティ
- ShouldRunNpmInstall: true(デフォルト)にしておくと、
VS でソリューションを開いた時やビルド時に、自動で npm install を実行 - ShouldRunBuildScript: 製品リリース用(Publish)ビルドの際、
自動で npm run build を走らせ、成果物を指定のフォルダに出力
- ShouldRunNpmInstall: true(デフォルト)にしておくと、
補足(各プロパティの意味と、実務での注意):
プロパティ 意味 SdkJavaScript プロジェクト SDK。 .csprojのMicrosoft.NET.Sdkに相当StartupCommandF5 で実行されるコマンド( npm run dev等)JavaScriptTestRootテストの探索対象フォルダ JavaScriptTestFrameworkテスト エクスプローラーとの統合(Jest / Vitest / Mocha) SpawnServerScript開発サーバーを別プロセスで起動するか BuildOutputFolderビルド成果物の出力先( dist)ShouldRunNpmInstallソリューションを開いた際に npm installを自動実行ShouldRunBuildScriptビルド時に npm run buildを実行するか ★
ShouldRunNpmInstallには注意点がある。【問題】 ・自動で npm install が走る=【package-lock.json が更新され得る】 → 意図しない依存の版上がり → チーム内で lock ファイルの差分が出る ★ ・オフライン環境で開くと失敗する ・開くたびに時間がかかる(キャッシュがあれば速いが) 【対策】 ・CI では【npm ci】を使う(lock を厳密に守る。install ではない) ・気になるなら ShouldRunNpmInstall を false にし、 手動 or CI で明示的に実行する
Condition="'$(Configuration)' == 'Debug'"の意味:Debug 構成のときだけ ShouldRunBuildScript = false → デバッグ時は本番ビルドを走らせない(Vite の dev server を使う) → Release / Publish のときは true のまま= npm run build が走る → 【この 1 行が「ビルドが重い」問題の解】である ★
1.0.0-alpha.x.xというバージョン:
原文が記録している通り、
この SDK は長らく alpha 版として提供されていた。
現在もバージョンを明示的にピン留めするのが安全である
(VS の更新で SDK の挙動が変わることがある)。
-
.esproj テンプレート(例:React with ASP.NET Core)を選ぶと、
フロントエンドとバックエンドがどうやって通信するかの仕掛け(プロキシ設定)が
自動で構築される。- SPA 側(Vite 等)のポート: localhost:5173
- API 側(C#)のポート: localhost:7200
-
開発中、SPA 側から /api/weather のようにリクエストを送ると、
Vite 側の開発用プロキシ(vite.config.ts に自動記述される設定)が、
裏側で自動的に C# 側の localhost:7200/api/weather へリクエストを転送し
CORS エラーに悩まされることがなくなる。
補足(自動生成される設定の中身): Visual Studio CodeによるSPA開発
で「対策 B(プロキシ)が優れている」と述べた構成を、
VS が自動で作ってくれる——というのがこの節の内容である。// vite.config.ts(テンプレートが生成するものの要点) export default defineConfig({ server: { proxy: { '^/api': { target: 'https://localhost:7200', secure: false, // 開発用の自己署名証明書を許容 } }, port: 5173, } });【リクエストの流れ(開発時)】 ブラウザ → localhost:5173/api/weather │ Vite の dev server が受ける │ /api で始まるので【転送】 ▼ localhost:7200/api/weather(ASP.NET Core) → ブラウザから見ると【同一オリジン】 → CORS が発生しない ★ → Cookie 認証もそのまま効く本番ではプロキシは存在しない点に注意する。
【本番の構成(例)】 ① SPA を ASP.NET Core の wwwroot に配置し、同一ドメインで配信 → MapFallbackToFile("index.html")([Spa Services] 参照) ② SPA を CDN / Static Web Apps に、API を別ドメインに → 【CORS の設定が必要になる】 ③ リバース プロキシ(nginx / Azure Front Door)で 同一ドメインに束ねる ★ 推奨開発時に CORS が起きない構成にしていると、
本番で初めて CORS に当たる——という事故が起こり得る。
本番と同じ構成をステージング環境で検証する必要がある。証明書についての補足:
・ASP.NET Core は開発用の自己署名証明書を使う dotnet dev-certs https --trust ・Vite 側は secure: false で検証をスキップする → 【開発時のみ】。本番の設定に持ち込まないこと
- Visual Studio 1 つで開発を完結させたい:
「C# のデバッグは VS、フロントエンドは VS Code」と画面を行き来するのが面倒で、
1 つの IDE、1 つの「デバッグ開始(F5)」ボタンで全てを制御したい場合に
最高のパフォーマンスを発揮 - CI/CD(ビルドパイプライン)を一本化したい:MSBuild の仕組みに乗っかっているため、
Azure Pipelines や GitHub Actions で「ソリューション全体のビルド」を実行するだけで、
フロントエンドの npm install & build も処理できる。
補足(CI/CD の一本化について、公平に): 2 番目の利点は実質的だが、
一本化が常に良いとは限らないので、両面を書いておく。# 一本化した場合(GitHub Actions) - run: dotnet publish -c Release # → .csproj のビルド + .esproj 経由で npm ci && npm run build # → 【1 コマンドで済む】★# 分離した場合 - run: npm ci --prefix ./client - run: npm run build --prefix ./client - run: dotnet publish -c Release # → 記述は増えるが、【何が起きているかが見える】
一本化(.esproj) 分離 記述量 少ない 多い 失敗箇所の特定 MSBuild のログに埋もれる 明確 ★ キャッシュ npm キャッシュを効かせにくい actions/setup-nodeのキャッシュが効く ★並列化 しにくい フロントとバックを並列ビルドできる 部分デプロイ しにくい フロントだけ再デプロイ、が可能 必要な環境 .NET SDK のみ(Node は SDK が呼ぶ) .NET SDK + Node.js 【規模による使い分け】 小~中規模、フロントとバックを常に同時にデプロイする → 【一本化で良い】 大規模、フロントとバックのリリース サイクルが違う → 【分離する】 → フロントは CDN、バックは App Service、と配置先も違う**判断の軸は「フロントとバックを常に同時にデプロイするか」**である。
同時なら一本化、別々なら分離——と考えると迷いにくい。
...
- Visual Studio での JavaScript と TypeScript
https://learn.microsoft.com/ja-jp/visualstudio/javascript/ - Visual Studio での JavaScript プロジェクト(.esproj)
https://learn.microsoft.com/ja-jp/visualstudio/javascript/javascript-project-system - Visual Studio での React と ASP.NET Core
https://learn.microsoft.com/ja-jp/visualstudio/javascript/tutorial-asp-net-core-with-react - ASP.NET Core での SPA の開発
https://learn.microsoft.com/ja-jp/aspnet/core/client-side/spa/intro
Tags: 移行, .NET開発, .NET Core, ASP.NET, ASP.NET Web API, ASP.NET SPA, JavaScript
このWikiは「Open棟梁Project」,「OSSコンソーシアム 開発基盤部会」によって運営されています。