You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This add-on shows how to compile a small **React (TypeScript)** front-end during `dotnet build/publish` using **Microsoft.TypeScript.MSBuild** — without converting the FBA into a full project. We keep the app single-file (`api.cs`) and place MSBuild config in **Directory.Build.props/targets** next to it.
347
+
348
+
> Why this approach
349
+
>
350
+
> ***Deterministic**: CI/CD calls `dotnet build/publish` and gets front-end assets.
351
+
> ***Agent-friendly**: No ad-hoc shell steps; one entry point.
352
+
> ***Isolated**: You can later swap to Vite/Webpack with minimal MSBuild changes.
353
+
354
+
### 24.1 Prerequisites
355
+
356
+
***Node.js** (runtime) is required; the NuGet package wires MSBuild targets but does **not** replace Node.
357
+
* Pin exact package versions via the **`nuget` MCP server** (see §18). Example directive (place at top of `api.cs`):
358
+
359
+
```csharp
360
+
#:package Microsoft.TypeScript.MSBuild@<ExactVersion> // pin via MCP nuget
├── package.json # NPM deps for React/TS type packages if desired
372
+
├── src/ # TypeScript/React sources
373
+
│ ├── main.tsx
374
+
│ └── app.tsx
375
+
└── wwwroot/ # Build output target for static files
376
+
└── index.html
377
+
```
378
+
379
+
> You can keep `package.json` very small (types only) because the **compiler is driven by MSBuild**. If you prefer a toolchain (Vite/Webpack), swap §24.5 “B” later.
380
+
381
+
### 24.3 ASP.NET static file plumbing (in `api.cs`)
382
+
383
+
Add static files so the built front-end is served from `/`:
384
+
385
+
```csharp
386
+
// after var app = builder.Build();
387
+
app.UseDefaultFiles(); // serves wwwroot/index.html by default
388
+
app.UseStaticFiles(); // serves files under wwwroot/*
> If you stay in **pure MSBuild** mode, `typescript` here only controls editor typings; **MSBuild invokes its own compiler** from `Microsoft.TypeScript.MSBuild`. Node is still required for the compiler runtime.
549
+
550
+
### 24.7 Running
551
+
552
+
```bash
553
+
# One command compiles TS and runs the API
554
+
dotnet run api.cs
555
+
# or build only
556
+
dotnet build
557
+
# or publish (assets go under publish/wwwroot)
558
+
dotnet publish -c Release
559
+
```
560
+
561
+
### 24.8 Testing & hardening
562
+
563
+
* Add an integration test that hits `/` (serves `index.html`) and `/assets/main.js` after `dotnet build`.
564
+
* For production, prefer **bundler mode** (§24.5-B) for code-split, minification, and cache busting.
565
+
* Use a **content hash** in asset filenames (via bundler) or append a version query (`/assets/main.js?v=…`) and set long-cache headers.
566
+
567
+
### 24.9 Troubleshooting
568
+
569
+
***`TypeScriptCompile` target not running** → Ensure `Directory.Build.props/targets` are in the **same directory** (or ancestor) as `api.cs`.
570
+
***Node not found** → Install Node, or set PATH in CI.
571
+
***Files not served** → Verify `app.UseDefaultFiles(); app.UseStaticFiles();` and that outputs land in `wwwroot/*`.
572
+
***Interop issues with older browsers** → Use bundler + transpilation to ES2017/ES2018 and polyfills as needed.
573
+
574
+
---
575
+
344
576
### Review Checklist
345
577
346
578
*[ ]`TargetFramework=net10.0`, `Nullable=enable`; AOT choice is deliberate
@@ -349,3 +581,13 @@ public sealed record User(Guid? Id, string Name);
0 commit comments