| name | azure-react-deployment |
| description | Azure deployment best practices for React applications (Vite SPAs on Azure Static Web Apps, Next.js on App Service or Container Apps). Use when creating deployment configs, Dockerfiles, staticwebapp.config.json, or GitHub Actions workflows for a React app on Azure. |
Azure Deployment for React Applications
Use this skill when deploying a migrated React app (Vite SPA or Next.js) to Azure.
When to Use This Skill
- Deploying a Vite React SPA to Azure Static Web Apps (recommended for Vite)
- Deploying a Next.js app to Azure App Service (Linux) or Azure Container Apps (for SSR)
- Creating a Dockerfile for a containerized Next.js standalone build
- Setting up GitHub Actions workflows for Azure deployment
Hosting Platform Selection
| Platform | Best for | Trade-offs |
|---|
| Azure Static Web Apps (SWA) | Vite SPA + separate API (Azure Functions optional) | Client-side only; SPA fallback routing built-in; free tier for hobby |
| Azure App Service (Linux, Node) | Next.js with SSR, PaaS convenience | Higher cost than SWA; needs next start |
| Azure Container Apps | Containerized Next.js standalone build, scale to zero | Requires Docker image + registry; slightly more setup |
| Azure Kubernetes Service (AKS) | Multi-app deployments, full K8s control | Over-provisioned for a single React app |
| Azure Blob Storage + Front Door / CDN | Static Vite SPA, ultimate low cost | No auth/routing config helpers; manual setup |
Recommendation:
- Vite SPA → Azure Static Web Apps (best fit)
- Next.js (any mode) → Azure Container Apps (containerized standalone build) or App Service if you prefer PaaS
Template Files
See the templates directory for ready-to-use files:
Vite → Azure Static Web Apps
Deployment pipeline (recommended)
- Push to
main branch of GitHub repo linked to the SWA resource
- GitHub Actions workflow builds Vite app (
npm ci && npm run build)
Azure/static-web-apps-deploy@v1 uploads dist/ to SWA
- SWA serves static assets from Azure's edge CDN + applies routing/auth from
staticwebapp.config.json
Key files at repo root
staticwebapp.config.json — controls SPA fallback, routes, auth, headers, MIME types
.github/workflows/azure-static-web-apps.yml — CI/CD workflow (SWA creates this automatically when you connect the repo)
SPA Fallback (critical)
Without this, deep links like /employees/edit/5 return 404 on refresh:
{
"navigationFallback": {
"rewrite": "/index.html",
"exclude": ["/images/*.{png,jpg,gif}", "/css/*", "/api/*"]
}
}
Proxy /api to a backend
If the .NET backend is elsewhere (e.g., App Service), add a proxy route:
{
"routes": [
{ "route": "/api/*", "rewrite": "https://your-backend.azurewebsites.net/api/*" }
]
}
Or use SWA linked APIs (Azure Functions) if you're migrating the backend too.
Environment Variables (Vite build-time)
import.meta.env.VITE_* values are baked into the bundle at build time. Configure them as GitHub Actions secrets and pass via env in the workflow:
- name: Build
env:
VITE_API_URL: ${{ secrets.VITE_API_URL }}
run: npm run build
SWA "application settings" (portal) are for the Functions API only — they do not affect the built React bundle.
Next.js → Azure Container Apps (recommended for SSR)
Enable standalone output
In next.config.js:
module.exports = {
output: 'standalone',
env: { },
};
This makes next build emit a minimal .next/standalone/ folder — the ideal shape for containerization.
Build & push image
Use the Dockerfile-nextjs template:
docker build -t myregistry.azurecr.io/employee-web:1.0 .
az acr login --name myregistry
docker push myregistry.azurecr.io/employee-web:1.0
Deploy with azd or az cli
az containerapp up \
--name employee-web \
--resource-group rg-employee \
--image myregistry.azurecr.io/employee-web:1.0 \
--ingress external \
--target-port 3000 \
--env-vars NEXT_PUBLIC_API_URL=https://api.example.com
Prefer azd up if you have Bicep/Terraform infra in infra/ — it wires everything together.
Next.js → Azure App Service (Linux, Node runtime)
Simpler than Container Apps if you don't want to manage images.
- Create App Service (Linux) with Node 20 LTS runtime
- Set startup command:
node server.js (if using output: 'standalone') or npm start (default)
- Deploy via
az webapp up, VS Code Azure extension, or GitHub Actions
- Configure app settings (env vars):
NEXT_PUBLIC_API_URL, etc.
App Service application settings are available at runtime (both server + client for NEXT_PUBLIC_*). Unlike Vite/SWA, Next.js reads env vars at runtime for server components and API routes.
Best Practices
1. Bake environment values correctly
| App type | Client vars available where |
|---|
| Vite SPA on SWA | Injected at build time — must be in the build workflow env |
| Next.js on App Service / Container Apps | NEXT_PUBLIC_* at build time; server env at runtime |
Never commit .env.production with secrets. Use Key Vault + managed identity for anything sensitive.
2. Use Managed Identity for backend calls
Prefer system-assigned managed identity + RBAC over API keys for Azure resources (Storage, Cosmos, Key Vault). The React frontend itself doesn't hold Azure credentials, but any Functions API or Next.js server code should.
3. Enable Application Insights
- Vite/SWA: add
@microsoft/applicationinsights-web + @microsoft/applicationinsights-react-js in App.tsx
- Next.js: same client-side setup +
applicationinsights package on the server for tracing SSR / API routes
4. Cache static assets aggressively
SWA + Front Door automatically apply cache headers for hashed assets (Vite emits filenames with content hashes). No additional config typically needed.
For Next.js containerized on App Service, ensure _next/static/** is served with Cache-Control: public, max-age=31536000, immutable.
5. HTTPS only + HSTS
- SWA: HTTPS is enforced by default with free managed certificate
- App Service: enable "HTTPS Only" in TLS/SSL settings
- Container Apps: ingress is HTTPS by default
6. Custom domains
Both SWA and App Service support custom domains with free managed certificates via Azure. Set up DNS CNAME records to the default Azure hostname.
7. Multiple environments
Use separate SWA/App Service resources per environment (dev/staging/prod). SWA supports preview environments per PR out of the box — very useful for review.
Angular → React Deployment Notes
| Old (Angular on Azure) | New (React on Azure) |
|---|
ng build --prod → dist/employee-manager/ | vite build → dist/ or next build → .next/ |
App Service (Node runtime) serving Angular via express | SWA (Vite) or App Service (Next.js with next start) |
web.config for IIS rewrite rules | staticwebapp.config.json for SWA |
environment.prod.ts fileReplacements | .env.production + build-time env vars |
polyfills.ts for older browsers | Vite/Next.js target modern browsers by default |
karma.conf.js in pipeline | vitest run in pipeline (much faster) |