Deploy Vite + React to IIS (Root Site)
A minimal, copy‑pastable checklist for Vite + React hosted at the site root (e.g. https://yourdomain/) on IIS.
1) vite.config.js (ESM)
Because your package.json contains "type": "module", use import/export. The base: '/' is for root deployments.
// vite.config.js
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react-swc'
export default defineConfig({
plugins: [react()],
base: '/', // deploying at site root
build: { outDir: 'dist', sourcemap: false }
})
2) Build
Generate an optimized production build into dist/.
npm run build
# output: ./dist (index.html + assets/)
3) Install URL Rewrite (one‑off)
SPA routing needs IIS URL Rewrite. Verify it’s installed or install it, then recycle the site.
%windir%\system32\inetsrvppcmd list modules | find "Rewrite"
:: In IIS Manager → server node → Modules → look for "RewriteModule"
4) Add web.config (SPA fallback)
Place this file inside the dist/ folder (next to index.html). It rewrites deep links to index.html so refreshes on routes like /services work.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<!-- Send all non-file, non-folder requests to index.html -->
<rule name="SPA Fallback" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
<!-- Exclude API calls from SPA rewrite -->
<add input="{REQUEST_URI}" pattern="^/api($|/)" negate="true" />
</conditions>
<action type="Rewrite" url="/index.html" />
</rule>
</rules>
</rewrite>
<!-- Optional: compression for static files -->
<urlCompression doStaticCompression="true" />
</system.webServer>
<!-- Optional: prevent caching of index.html so new builds load instantly -->
<location path="index.html">
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Cache-Control" value="no-store, no-cache, must-revalidate" />
<add name="Pragma" value="no-cache" />
<add name="Expires" value="0" />
</customHeaders>
</httpProtocol>
</system.webServer>
</location>
</configuration>
/ but direct deep links (e.g. /services) will 404.5) IIS site settings (one‑off)
Point the site’s physical path to your deployment folder (e.g., C:\inetpub\wwwroot). Ensure these settings:
- App Pool: No Managed Code, Pipeline: Integrated
- Windows Features: Static Content enabled
- IIS Manager → Default Document: includes
index.html(preferably first)
6) Deploy (PowerShell mirror)
Mirror your fresh build into the IIS root. Re‑run after each build.
$build = "C:\code\katmaid-react\dist" # change to your path
$target = "C:\inetpub\wwwroot" # IIS site root
New-Item -ItemType Directory -Force -Path $target | Out-Null
robocopy $build $target /MIR
7) Verify deep links
Test both the homepage and a deep link directly (e.g., /services). If deep links 404, URL Rewrite is missing or the rule isn’t applied.
8) Temporary workaround (no server changes)
If you can’t install URL Rewrite yet, switch to hash routing so URLs look like #/services and avoid server rewrites.
// main.jsx (or similar)
import { createRoot } from 'react-dom/client'
import { HashRouter } from 'react-router-dom'
import App from './App'
createRoot(document.getElementById('root')).render(
<HashRouter>
<App />
</HashRouter>
)
Troubleshooting:
- 500.19: Usually URL Rewrite missing or malformed
web.config. - Works at
/but 404 on refresh: Rewrite rule not applied. - Old UI after deploy: Add the
index.htmlno-cache headers inweb.config.

















