Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I setup react-router clean URL's with IIS?

React-Router enables your ReactJS app to become a SPA through simple routing components. When deploying to IIS, everything works fine when setup using bashHistory. However, when I try to use browserHistory, IIS is trying to return a directory instead of allowing React-Router to grab and resolve the route. How do I setup React-Router to work in an IIS environment?

like image 826
jOshT Avatar asked Oct 10 '16 22:10

jOshT


People also ask

How do I add a 404 page to my React router?

Routing to the 404 PageYou specify the URL path and the element you want to render at that route. The 404 page displays for paths that don't exist on the website. So, instead of specifying the path, use an asterisk (*). Using * renders the NotFound component for all the URLs not specified in routes.

How does IIS URL Rewrite work?

The concept of URL rewriting is simple. When a client sends a request to the Web server for a particular URL, the URL rewriting module analyzes the requested URL and changes it to a different URL on the same server.

How deploy React application in IIS?

Open Control Panel and then click on the "Programs and Features". Click on "Turn Windows features on or off". Select Internet Information Services and click on the OK button. To see whether or not IIS is enabled, press Windows + R key and type inetmgr and click on OK.

What is rewrite module IIS?

About the URL Rewrite module The Microsoft URL Rewrite Module 2.0 for IIS 7 and above enables IIS administrators to create powerful customized rules to map request URLs to friendly URLs that are easier for users to remember and easier for search engines to find.


2 Answers

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.

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

  2. 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>
  1. In your base html page (index.html) add a <base/> tag with a href attribute to your app.

<base href='/path/to/my/app'/>

like image 106
jOshT Avatar answered Sep 21 '22 10:09

jOshT


Just building on this answer for anyone interested. If your like me and need to deploy your app via script. Here are the powershell scripts necessary to create the webconfiguration above.

This installs the URL Rewrite on the server.

    #Install IIS UrlRewrite
    If(Test-Path c:/msi) {
    Invoke-WebRequest 'http://download.microsoft.com/download/C/F/F/CFF3A0B8-99D4-41A2-AE1A-496C08BEB904/WebPlatformInstaller_amd64_en-US.msi' -OutFile c:/msi/WebPlatformInstaller_amd64_en-US.msi
    Start-Process 'c:/msi/WebPlatformInstaller_amd64_en-US.msi' '/qn' -PassThru | Wait-Process
    cd 'C:/Program Files/Microsoft/Web Platform Installer'; .\WebpiCmd.exe /Install /Products:'UrlRewrite2,ARRv3_0' /AcceptEULA /Log:c:/msi/WebpiCmd.log
    }
    else {
    New-Item c:/msi -ItemType Directory
    Invoke-WebRequest 'http://download.microsoft.com/download/C/F/F/CFF3A0B8-99D4-41A2-AE1A-496C08BEB904/WebPlatformInstaller_amd64_en-US.msi' -OutFile c:/msi/WebPlatformInstaller_amd64_en-US.msi
    Start-Process 'c:/msi/WebPlatformInstaller_amd64_en-US.msi' '/qn' -PassThru | Wait-Process
    cd 'C:/Program Files/Microsoft/Web Platform Installer'; .\WebpiCmd.exe /Install /Products:'UrlRewrite2,ARRv3_0' /AcceptEULA /Log:c:/msi/WebpiCmd.log
    }

And here is how you add the rules.

Add-WebConfigurationProperty -pspath "$IISPath\MyWebsite" -filter "system.webServer/rewrite/rules" -name "." -value @{name='Home';stopProcessing='True'}
Set-WebConfigurationProperty -pspath "$IISPath\MyWebsite"  -filter "system.webServer/rewrite/rules/rule/match" -name "url" -value ".*"

Add-WebConfiguration -pspath "$IISPath\MyWebsite" -filter "system.webServer/rewrite/rules/rule[@name='Home']/conditions" -value @{ input="{REQUEST_FILENAME}"; matchType="IsFile"; negate="true" }
Add-WebConfiguration -pspath "$IISPath\MyWebsite" -filter "system.webServer/rewrite/rules/rule[@name='Home']/conditions" -value @{ input="{REQUEST_FILENAME}"; matchType="IsDirectory"; negate="true" }
Add-WebConfiguration -pspath "$IISPath\MyWebsite" -filter "system.webServer/rewrite/rules/rule[@name='Home']/conditions" -value @{ input="{REQUEST_URI}"; pattern="^/(docs)"; negate="true" }

Set-WebConfigurationProperty -pspath "$IISPath\MyWebsite"  -filter "system.webServer/rewrite/rules/rule/action" -name "type" -value "Rewrite" 
Set-WebConfigurationProperty -pspath "$IISPath\MyWebsite"  -filter "system.webServer/rewrite/rules/rule/action" -name "url" -value "index.html"

These scripts can be executed locally or remotely via Invoke-Command in Powershell.

Also I had some trouble with React Router warnings and with using the base tag in my header on index.html. This link is fairly helpful.

https://github.com/ReactTraining/react-router/issues/4006

I essentially change my React-Router package and History package to version 3.x and set the config in my router to get rid of the deprecation warnings. This is my react router now.

import { useRouterHistory } from 'react-router'
import { createHistory } from 'history'

const history = useRouterHistory(createHistory)({
basename: '/base-path'
})

ReactDOM.render(
  <Router history={history}>
 ....
like image 38
Puerto Avatar answered Sep 25 '22 10:09

Puerto