17

I am using react-router and have put it in it, but I noticed that when I start at the landing page and go through all my routes it works. If I just type in a path url I get a 404.

Am I guessing this has something to do with the server not knowing how to pass it off to my client routes?

I found this post but I am a bit confused with the answers as some say to update the web.config file but I don't have one as it is a Reactjs only.

Edit

Here is what I have now for my rewrite

enter image description here

I am now getting a white page when I try to navigate to a URL that is not the index page.

When I look at my console. I see

Uncaught SyntaxError: Unexpected token <

which goes to main.js and complains about this "<!DOCTYPE html>" it almost seems as my index.html was merged into the javascript file.

Ratan Uday Kumar
  • 5,738
  • 6
  • 35
  • 54
chobo2
  • 83,322
  • 195
  • 530
  • 832

5 Answers5

25

The key to getting React-Router to work with IIS is to setup URL Rewrite rules. After looking at how some others have setup AngularJS SPA apps with IIS, I have come up with the following solution.

Download and install URL Rewrite on your server (development and production)

Setup rule to catch any url routes that ARE NOT files and ARE NOT directories. Optionally, you can negate any actual directories that you want serve regularly. More info can be found here on Microsoft's Documentation

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.webServer>
  <rewrite>
    <rules>
      <rule name="ReactRouter 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="^/(docs)" negate="true" />
        </conditions>
        <action type="Rewrite" url="index.html" />
      </rule>
    </rules>
  </rewrite>
</system.webServer>
</configuration>

In your base html page (index.html) add a tag with a href attribute to your app.

<base href='/path/to/my/app'/>
Mohit Tilwani
  • 2,716
  • 1
  • 13
  • 13
  • 3
    Ok, I installed Url Rewrite, I made a web.config and pasted in your code. I then added to the body ' but I have no clue what to put as the path or if I put it in the right area. – chobo2 Aug 08 '18 at 20:58
  • 1
    @mohit can you tell the location.. where to add the above web.config file. – prudhvi259 Nov 03 '21 at 06:25
5

To expand a little bit you do need the URL rewrite package as Mohit explained but you don't need to write your own web.config file, you can do it straight from IIS Manager if you want.

Once you have URL Rewrite installed, you may have to reboot or restart IIS, you should see it on the dashboard for the sites. I do it at the site level and not the server level.

In there you are going to add a rule. It must Match the pattern for the request URL using regular expressions with the pattern .* This will match all urls sent by the browser.

In the conditions you will need two conditions that must Match All. There are two inputs you need:

  • {REQUEST_FILENAME} is Not a File
  • {REQUEST_FILENAME} is NOT a Directory

No pattern is needed on these.

Finally in the Action section you need to Rewrite with the rewrite url to be / appending the query string. This will keep everything being sent to react-router and not absorbed by the server.

At this point you might want to stop processing more rules unless you have other unrelated business logic that also needs to run.

This will configure IIS to send all requests to the root of the site which should be one of the default documents as setup in IIS, most likely index.html. From there React-router will pick it up.

JeffBaumgardt
  • 1,378
  • 3
  • 16
  • 24
  • I think I did what you wrote, but it still is not working. I now get a blank page(not a 404 anymore). I do see something on the console but not sure if it is related: Uncaught SyntaxError: Unexpected token <. Which when I follow it goes to " " . I posted screenshot of my urlrewite – chobo2 Aug 08 '18 at 21:14
  • The url rewrite looks good. As for the Syntax error it seems like something didn't compile correctly. – JeffBaumgardt Aug 08 '18 at 21:23
  • 2
    When I navigation to http:myhomepage everything loads fine. It is not http:myhomepage/somepage is when I get the problem. So I am not really sure it is a compile problem – chobo2 Aug 08 '18 at 21:26
  • I might of got it, I had src="main.js" but I think with this url rewriting I need "/main.js". – chobo2 Aug 08 '18 at 21:31
  • 1
    Though I am not sure how to get webpack to build the "src" that way yet. I am manually editing the file. – chobo2 Aug 08 '18 at 21:33
  • Yeah same here, I copied the web.config inside the ‘build’ output folder then it simply works. I tried coping inside the ‘src’ and project root folder. I thought this command ‘npm run build’ would copy the web.config to the build folder. – Athar May 29 '19 at 14:55
  • @JeffBaumgardt Would it be possible for you to give an example of what you wrote? I'm now learning how to use the iis and I don't understand how to do what is in the answer – Catarina Dec 06 '19 at 16:33
  • I'm sorry it's been a very long time since I wrote this up. If the steps in my answer don't match your IIS screens it could be due to a newer version of IIS since my post. – JeffBaumgardt Dec 09 '19 at 19:11
1

Some remarks to Mohit Tilwani answer

say your url is http://localhost/mySubDir

  1. in web.config add rules to prevent rewrite of js, css files:
 <system.webServer>
  <rewrite>
        <rules>
          <rule name="ReactRouter 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="^/(docs)" negate="true" />
              <add input="{URL}" negate="true" pattern="\.js$" />
              <add input="{URL}" negate="true" pattern="\.css$" />
            </conditions>
            <action type="Rewrite" url="index.html" />
          </rule>
        </rules>
      </rewrite>
 </system.webServer>
  1. in index.html
<base href="%PUBLIC_URL%/" /> 
  1. in package.json add the line:
 "homepage": "http://localhost/mySubDir",
  1. in index.js you add the subDir part
const baseUrl = '/mySubDir/';
const rootElement = document.getElementById('root');
ReactDOM.render(
        <BrowserRouter basename={baseUrl}>
            <App />        
        </BrowserRouter>
        </ThemeProvider>
        </Suspense>
    </StoreContext.Provider>
    ,
    rootElement);
Citizen-Dror
  • 843
  • 9
  • 17
0

I have this web.config file into some of my PROD pages using Plesk as a Host. I've manually added this web.config to the React page root folder, hopefully, this might work with any IIS Server:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.web>
    <compilation defaultLanguage="c#" />
  </system.web>
    <system.webServer>
        <httpErrors errorMode="Custom" existingResponse="Replace">
            <remove statusCode="404" subStatusCode="-1" />
            <error statusCode="404" path="/" responseMode="ExecuteURL" />
        </httpErrors>
        <tracing>
            <traceFailedRequests>
                <add path="*">
                    <traceAreas>
                        <add provider="ASP" areas="" verbosity="Verbose" />
                        <add provider="ASPNET" areas="AppServices,Infrastructure,Module,Page" verbosity="Verbose" />
                        <add provider="ISAPI Extension" areas="" verbosity="Verbose" />
                        <add provider="WWW Server" areas="Authentication,Cache,CGI,Compression,FastCGI,Filter,Module,RequestNotifications,RequestRouting,Rewrite,Security,StaticFile,WebSocket" verbosity="Verbose" />
                    </traceAreas>
                    <failureDefinitions statusCodes="500" />
                </add>
            </traceFailedRequests>
        </tracing>
    </system.webServer>
</configuration>
0

After updating the web.config, I had a different issue when refreshing the page it was lead to a blank page with a console error as here

Able to resolve the issue by adding the below tag to the Head section of index.html

<base href="https://mydomain/" target="_blank">
Thinira
  • 361
  • 3
  • 8