React – Deploy to a Sub-Folder

Table of Contents
Overview
This what you will need to know if you are building a react-app on top of an ASP.NET Web API. So the API will sit at the root and the UI in a sub-folder in order to access Active Directory credentials for an Intranet application.
Package.json
First step is to update the package.json file from the root of your application. Add an entry for homepage in the same section with “name” towards the top of the JSON file. The URL should be the domain plus the sub-folder.
{
"name": "YOUR_APP_NAME",
"version": "0.1.0",
"private": true,
"homepage": "http://domain-name/sub-folder-name",
"dependencies": {
"axios": "^0.20.0",
..............
Next inside of the package.json file under “scripts” update the “build” value.
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build && move build sub-folder-name",
"test": "react-scripts test",
When you run npm run-script build the application will generate the files into a folder with the same label as the sub-folder-name.
HashRouter Method
From the router add the following
import { HashRouter } from 'react-router-dom';
...
return (
<div>
<HashRouter >
<Route exact path="/" component={Welcome} />
<Route path="/home" component={Home} />
</HashRouter>
</div>
);
Navigation
import { Link } from 'react-router-dom';
...
<Link to="/home">
...
</Link>
If the <hashrouter> does not work
Router Method – Not ideal, but it works
Add the BrowserRouter and force the refresh.
index.js
import React from 'react';
import './index.css';
import App from './App';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom'
ReactDOM.render(
<BrowserRouter forceRefresh={true}>
<App />
</BrowserRouter>,
document.getElementById('root')
);
I have installed react-router and react-dom-router. If you are using something else then, this may not apply to you.
In the router update as follows:
<Switch>
<Router basename={'/sub-folder-name'}>
<Route exact path="/" component={Welcome} />
<Route exact path="/blog" component={Home} />
<Route exact path="/blog-post/:Id" render={(props) => <BlogPost Id={props} /> } />
</Router>
</Switch>
Adding the property of basename with the sub-folder-name om the JSX Router tag.
You should still be able to run this application locally.
Setting up IIS
If you are running IIS then make the following changes to the web.config in the ASP.NET Web API file between the <system.webServer> tags.
<rewrite>
<rules>
<rule name="React Routes" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
<add input="{REQUEST_URI}" pattern="^/(api)" negate="true" />
</conditions>
<action type="Rewrite" url="/" />
</rule>
</rules>
</rewrite>
From IIS Manager go to Error Page

Modify the 404 error:


This will take users back to the root or you can put a custom redirect that will take them to the last page they visited.
OR
You can handle the 404 error from the API. With ASP.NET Web API just add the following code to the web.config file. In the example below “/app” is the root folder for the UI.
<configuration>
...
<configSections>
...
</configSections>
<appSettings>
...
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5.2" />
<httpRuntime targetFramework="4.5.2" />
<customErrors mode="On" >
<error statusCode="404" redirect="/app" />
</customErrors>
</system.web>
You must be logged in to post a comment.