Hosting React applications on Windows servers using IIS is a common requirement in enterprise environments, especially when your organization already relies on Microsoft’s infrastructure. Unlike a Node.js server, IIS serves static files and does not natively support client-side routing, so you need to configure it properly to support your React SPA.
In this article, you’ll learn:
- How to build and package your React app for production
- How to set up a website (or application) in IIS
- How to configure URL rewrite rules so that client-side routes resolve correctly
- How to manage permissions, bindings, and other deployment details
- Tips to troubleshoot common problems
Let’s get started.
Build Your React Application for Production
Before deploying, you need a production-ready build (static files) of your React app:
1. In your project root, ensure your package.json has the correct homepage field (especially if hosting under a subpath). For example:
{
"name": "my-app",
"version": "0.1.0",
"homepage": "/app1", // if your app will be under https://yourdomain.com/app1
...
}
Setting homepage helps generate correct paths in your build artifacts.
2. Run:
npm run build
This will produce a build folder containing the optimized, static files (HTML, JS, CSS, images, etc.).
3. Verify locally (for example, using a simple static server) to confirm that the build works before deploying to IIS.
Prepare the Server and Enable IIS Features
On the Windows server where you will host:
- Ensure Internet Information Services (IIS) is installed (including static content support).
- Install the URL Rewrite module in IIS (this is critical for handling SPA routes).
- Make sure Windows firewall or network settings allow HTTP (and HTTPS) traffic to the port you intend to use (e.g. port 80 or 443).
- Create (or choose) a folder where your build contents will reside, e.g. C:\inetpub\wwwroot\MyReactSite.
Create a Site or Application in IIS
1. Open IIS Manager (inetmgr).
2. Under the server node, right-click Sites → Add Website… (or optionally add an Application under an existing site).
- Site name: choose a friendly name (e.g. MyReactApp)
- Physical path: point this to the folder where you will copy the build files
- Binding: set the host name, port, and optionally HTTPS certificate
3. Assign an Application Pool to the site. Use a pool with .NET v4.0 (or appropriate identity) and ensure it can run under the correct permissions.
4. Confirm that Default Document is configured: ensure index.html is among the default documents (so that visiting the root URL serves your React entry point).
Copy the Build Files to the Server
From your local machine (or a CI/CD pipeline), copy the entire contents of the build folder into the site’s physical path on the server (e.g. C:\inetpub\wwwroot\MyReactSite). Overwrite any existing content.
Make sure file permissions allow the IIS process (e.g. the Application Pool identity, or IUSR / IIS_IUSRS) to read these static files.
Add a web.config File for SPA Routing
React SPAs typically rely on client-side routing (e.g. React Router). If a user refreshes a route URL such as /about, IIS will try to find a folder or file named about and return 404. To avoid this, you need a rewrite rule so that all non-file, non-directory requests fall back to index.html.
Place a web.config in the root of your deployed React app (same folder as index.html). For example:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<!-- Static file handling rule -->
<rule name="StaticAssets" stopProcessing="true">
<match url="([\S]+[.](html|htm|js|css|png|gif|jpg|jpeg|svg|ico|json))" />
<action type="Rewrite" url="{REQUEST_URI}" />
</rule>
<!-- React SPA fallback rule -->
<rule name="ReactRoutes" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="/index.html" />
</rule>
</rules>
</rewrite>
<staticContent>
<!-- Optionally add MIME types (e.g. for .json) if missing -->
<remove fileExtension=".json" />
<mimeMap fileExtension=".json" mimeType="application/json" />
</staticContent>
</system.webServer>
</configuration>
This web.config ensures:
- Requests for actual static files (e.g. .js, .css, images) are served normally.
- All other routes (that aren’t real files / directories) will be rewritten to index.html, letting your React app router handle them.
Test Access and Routing
- In IIS Manager, right-click your site → Manage Website → Browse.
- The homepage (/) should load your React application.
- Navigate to deep routes (e.g. /about, /dashboard) directly or by refreshing. Confirm the page renders correctly (no 404).
- Check your browser’s developer console and network tab for any failed resource loads.
- If you have APIs or backend under a subpath (e.g. /api), ensure your rewrite rules exclude those paths (so you don’t inadvertently rewrite API requests). You can add conditions to your rule (e.g. {REQUEST_URI} doesn’t start with /api) to prevent rewriting API calls.
Handling Applications Under Subpath
If your React app is deployed not at the root (e.g. /app1), you’ll need to:
- Set the homepage field in package.json (e.g. "homepage": "/app1") so that assets reference the correct subpath
- Adjust the web.config rules so fallback rewrites use the subpath base
- Possibly update your React Router base path configuration
For example, in web.config, you may rewrite to /app1/index.html rather than /index.html.
Permissions, Logging, and SSL
- Confirm that the Application Pool identity has read access to your build folder.
- Enable Failed Request Tracing (FREB) or examine IIS logs (under %SystemDrive%\inetpub\logs\LogFiles) if routes don’t resolve.
- If using HTTPS, configure a proper certificate binding in IIS, and optionally enforce HTTP → HTTPS redirection (via another rewrite rule).
- Consider adjusting caching headers or compression settings in IIS for performance.
Common Pitfalls & Troubleshooting
- Blank page / missing JS or CSS: likely your build references root paths (/static/js/...) but your app is under a subpath. Confirm homepage was set and rebuilt accordingly.
- 404 on refresh: means the rewrite rule isn’t catching the route; maybe URL Rewrite module isn’t installed, or your web.config is malformed.
- Rewrite loops: if your React router or backend also directs / paths, you might get redirect loops. Adjust conditions or paths to exclude API endpoints.
- Permission denied: ensure the IIS process identity can access the content directory.
- Mime types missing: if encountering “unknown MIME type” errors for JSON, fonts, etc., add those via <mimeMap> in web.config.
- Binding conflicts: ensure your site’s binding (hostname, port) is not conflicting with other IIS sites.
Conclusion
Deploying a React application on IIS isn’t overly difficult, but requires careful setup of static file serving and URL rewriting so that your client-side routing functions properly. With a properly built React bundle, the right web.config fallback rules, correct permissions, and IIS bindings, your React SPA can run seamlessly under IIS.