Deploying React (Router) app to the subfolder on server

  • May 2018 - Updated to match React Router v4 API.
  • September 2019 - Updated to match React Router v5 API, added React Create App part.

If you ever had to deploy React Router app to the subfolder on the server, you know what the problem is. Routes will get messed up once you upload it to the server. Here are two solutions I use in these cases.

Easy way, just use HashRouter

The easiest way to achieve this is to use HashRouter instead of BrowserRouter.

import { HashRouter, Route } from 'react-router-dom';

// Then in render
<HashRouter>
  <Route path='/' component={ Home } exact />
  <Route path='/about' component={ About } exact />
  {/*...*/}
</HashRouter>

This is the best approach if your subfolder name changes (for example, if folder name is a build version). But you'll have /#/ included in the every URL. If this bothers you, check the second solution.

Example of the routes

  • http://yourserver.com/path/to/subfolder/
  • http://yourserver.com/path/to/subfolder/#/about
  • http://yourserver.com/path/to/subfolder/#/search

Hard way, setting base path by hand

If you want to keep browser history implementation, you'll need to change few things. First, we need to update our routes to include full absolute path to the subfolder.

Using React Router's basename

As Davis Cabral pointed out in the comments, instead of manually adding publicPath to all routes, it can be achieved by using React Router's basename prop.

import { BrowserRouter, Route } from 'react-router-dom';

// Then in render
<BrowserRouter basename='/path/to/subfolder/'>
  <Route path='/' component={ Home } exact />
  <Route path='/about' component={ About } exact />
  {/*...*/}
</BrowserRouter>

Doing it by the hand

I define my routes something like this:

const publicPath = '/path/to/subfolder/';

export const routeCodes = {
  HOME: publicPath,
  SEARCH: `${ publicPath }search`,
  ABOUT: `${ publicPath }about`,
};

// Then you can use them like this
// <Route exact path={ routeCodes.ABOUT } component={ About } />

Setting up .htaccess file

Once uplodaded to the server any route (but root /) will return 404 error. For example, if you try to open http://yourserver.com/path/to/subfolder/about, server will look for file (or folder) named about in the app subfolder. As it doesn't exist, it will fail with 404.

You'll need to add a simple .htaccess file, in order to tell the server to fallback to our index.html file. This is the same configuration we would use if the application was on the server root, just with a different absolute path to our index file.

RewriteEngine On
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^ - [L]

# Fallback all other routes to index.html
RewriteRule ^ /path/to/subfolder/index.html [L]

Now our example routes will look like this

  • http://yourserver.com/path/to/subfolder/
  • http://yourserver.com/path/to/subfolder/about
  • http://yourserver.com/path/to/subfolder/search

Notice about webpack's output -> publicPath configuration

If you are using publicPath in webpack's output object, make sure you either remove it or update to match your server build path. Removing it is easier, as it will create relative links, which should work with your new configuration.

output: {
  publicPath: '/', // Remove, or update it
  path: './build',
  filename: 'app-[hash].js',
},

Create React App

A lot of people are using Create React App. To deploy it in subfolder, you can set homepage in your package.json, for more details check their documentation


I'm also interested if anyone has different/better ideas, cheers!

Comments (29)

And
24. Nov 2017, 12:19

Thanks!

Wilfried
20. Feb 2018, 13:39

Thank you, helped me to solve my routing problem on sub folders.

Biswajit
02. Mar 2018, 10:38

Can you please tell me how I will add .htaccess file, if I am deploying into IIS server.My app is in sub folder.

I donot have access to iis server. I will do deploy using jenkins.

I will appreciate your help.

Stanko
02. Mar 2018, 16:50

Hello @Biswajit,

Unfortunately, I can't help you with that as I have no experience with IIS, but a quick search provided me with Translate .htaccess Content to IIS web.config. Hopefully that will help you.

Cheers!

Biswajit
06. Mar 2018, 06:14

I solved this problem by using HashRouthing instead of BrowserRouting. Just I want to know what will be the wrong of using it.

Stanko
06. Mar 2018, 10:42

As I mentioned in the article already, the biggest drawback is that you'll have /#/ in your URLs.

Davis Cabral
23. Mar 2018, 20:42

You can use the Router prop basename for this.

<Router basename={ '/subdir' } history={ history }>
</Router>
Mikkel
12. Apr 2018, 11:24

Where are you storing the .htaccess file?

Stanko
12. Apr 2018, 13:46

Hey @Mikkel, .htaccess should be at the root of your project (where your index.html is).

@Davis, that is pretty neat, I missed that prop, thanks!

TheKid_||_
11. May 2018, 02:40

@Davis is the best solutions ;D

Ram
07. Jul 2018, 10:48

@Stanko:

Instead of this snippet,

<BrowserRouter basename='/path/to/subfolder/'>

can't we use this one ?

<BrowserRouter basename={location.pathname}>

This make the path configurable and this will work even if the path of subfolder changes, what do you feel about this?

Stanko
09. Jul 2018, 12:26

Hello Ram,

That won't work as location.pathname is dynamic property. For example it will be / on your home page, but something like /users/view/1 on user profile. Then all of your links would be relative to /users/view/1 instead of /.

Cheers!

Eugene
06. Sep 2018, 15:55

Thanks Stanko, you're a legend!

Was looking for a solution for the past couple of hours and this worked like magic.

Tin Htun
28. Sep 2018, 06:28

Thanks a lot! You save my day.

Salitha
22. Jan 2019, 03:49

This works fine! You saved my day.. Thanx a lot :D

Keyra
05. Mar 2019, 18:00

Thanks for this useful post! I have a question, what if I don't want to have # in my URLs, but I don't know the path on coding / compilation time? I need to have a package, that then can be deployed at any server (root, subfolder, whatever)

Stanko
05. Mar 2019, 21:10

Hello Keyra,

I can't think of a way to do it dynamically in a library, without using hash routing. If you figure out a way, please share the solution.

Cheers!

Robert
18. Mar 2019, 17:35

Hi, thanks for the write up, I just wanted to add that you can use

<Router basename={ process.env.PUBLIC_URL }>

then add

"homepage": "your url plus sub-directory"

to "package.json", and you should be good to go

Charlie
27. Mar 2019, 23:11

@Robert

Thanks for you comment man! I've been searching around how to work the build react app on IIS. Im using connected react router and i set my homepage from what you've said there, setting the basename for history

history = createBrowserHistory({basename: `${process.env.PUBLIC_URL}`
}) 

and voila! when the page refreshed, the 404 error page was gone. Thanks again!

Shubham Kesarwani
05. Apr 2019, 04:29

In my case there are two projects in two different subdirectories. and based on request i want to redirect to that particular project.

For e.g. www.test.com/us should go to project residing in 'us' directory and same should happen with www.test.com/in

RewriteRule ^ /path/to/subfolder/index.html [L] How can I get subfolder dynamically from url.

Please help

Amar
13. Jun 2019, 12:22

How to deal this concept with Create React App? As, I have doubt regarding setting Public path in webpack.

Dave
10. Sep 2019, 19:23

Maybe this changed in a newer version of ReactRouter? I get: Failed to compile ./src/App.js Line 45: 'hashHistory' is not defined no-undef

Stanko
10. Sep 2019, 19:42

That is correct Dave, I just updated the post.

Cheers!

Catarina
16. Dec 2019, 14:47

Hi! It helps me in some things but I still can't use routes. I got error 404. I'm using create-react-app and the project is hosted on iis Someone can help?

Stanko
16. Dec 2019, 14:53

Hi Catarina,

I guess you haven't used hash routing. That means you still need to setup proper server redirections. If you are using appache, you should check Setting up .htaccess file section in this post.

Cheers!

Ali Lishan
17. Dec 2019, 13:32

GREAT!!!!! I cannot thank you enough ... i have been searching high and low. And you updated the post ! .. You my man .. are a Legend!

Judy
13. Feb 2020, 16:10

Great article. This solves my bookmark URL issue without adding a web.config file.

greatghoul
03. Apr 2020, 03:03

Great, you saved my life!

Andrei
13. May 2020, 15:18

Thank you! Very helpful!