17

I'm attempting to use the static index.html file generated by npm run build, along with react-router. the tl;dr is; i do not want a client server, I want the app to be loaded by opening the index.html file located in the build folder and still have BrowserRouter be able to route between components. At the moment, the page will load the 'home' component if I exclude the 'exact' prop in the route path, meaning it knows that it's out there somewhere, I just don't know how to configure the router to know that 'C:/Users/Myself/Project/app/build/index.html' is equal to the path of '/' and route to each component thereafter. if the exact prop is included, it just loads the standard 404 component. How should i configure the BrouserRouter basename, and/or the package.json "homepage" in order to route to the index.html-> load 'home' component when the page is initially opened?

things I do not want to do: - serve the build folder. - configure webpack - have the app accessible from 'http://localhost:XXXX' - change to use HashRouter (I want access to props.history.push)

In my mind, if the app can show the 'home'component without specifying exact, it means that it can reach it under certain circumstances, and i'm just not specifying what the index path is properly, i.e it is somewhere out there at like ../project/build/index.html/somewhere

I have already configured the package.json to have "homepage": ".", and have specified the BrowserRouter basename={'/build'}

My BrowserRouter:

<BrowserRouter basename={'/build'}>
   <Routes />
</BrowserRouter>

My routes.js file:

const Routes = (props) => {
  return (
    <div>
      <Switch>
        <Route path={routes.HOME} component={Home} />
        <Route render={(props) => <div>404 - Not Found</div>} />
      </Switch>

    </div>
  )
}

my package.json:

{
  "name": "cra",
  "version": "0.1.0",
  "private": true,
  "homepage": ".",
  "dependencies": {
    "react": "^16.8.6",
    "react-dom": "^16.8.6",
    "react-redux": "^7.0.2",
    "react-router-dom": "^5.0.0",
    "react-scripts": "2.1.8",
    "redux": "^4.0.1",
    "redux-logger": "^3.0.6",
    "redux-thunk": "^2.3.0"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "browserslist": [
    ">0.2%",
    "not dead",
    "not ie <= 11",
    "not op_mini all"
  ],
  "devDependencies": {
    "node-sass": "^4.11.0"
  }
}

I want the end result to set c:/users/myself/project/app/build/index.html to equal route 'home' ('/').

I'm willing to accept that this is not possible, but as stated above, being able to access it from an inexact path leads me to believe i can make it exact and am just messing up the route config

Dsabadash
  • 445
  • 1
  • 4
  • 12
  • Are you using create-react-app? Not sure what you mean by you want it to be client side only because react is a client only library. If your using create-react-app then when you run npm build it will bootstrap your project and will default use index.html. React is a client only library so unless your using a server side rendering library like nextjs or something your project will be a client side only project no matter what. If your viewing it on localhost it is just a developement server using node but once you build your project it will be client side only. – Steve K Apr 14 '19 at 00:31
  • 1
    sorry, to sepcify: yes, I understand it's completely client-side. All i'm trying to avoid is having to run a server on the client to serve the index.html file – Dsabadash Apr 14 '19 at 00:35
  • I guess I just don't understand what you are saying. You don't run a server on the client side as it is not possible to do that hence the name client. When you build the app it bundles everything that you have done into one javascript file so no server is involved. You only use node for development purposes. – Steve K Apr 14 '19 at 00:38
  • 1
    the issue is: npm run build does indeed package everything into one file, but that causes a breakdown in the react-router that will not recognize the open file as the "index" path, and thus not load any components besides the default 404 component, and i don't want to run a client server to serve the file, because i don't want to have to access the app from http://localhost – Dsabadash Apr 14 '19 at 02:51
  • I'm actually interested in why you don't want to, say, run python -m http.server for serving your built application after generating them with npm run build? Since if you want to deploy it, you'd be deploying it in a web server anyway. – mfakhrusy Apr 14 '19 at 05:55
  • 1
    oh! the reason is because I want to inevitably access the app through electron, I would much prefer to access the app through a static file then have to serve it, and point the electron container at the given localhost port- i know from a user perspective there will be no difference in the app's functionality, but In my mind if the app can also be accessed through the main browser, it defeats the purpose of using electron (for this situation) entirely. I want the app to be downloadable/usable locally without it being deployed to a web server somewhere, and no client server is a personal pref – Dsabadash Apr 14 '19 at 20:59

4 Answers4

13

If your application is hosted on a static file server, you need to use a <HashRouter> instead of a <BrowserRouter>.

FAQ.md#why-doesnt-my-application-render-after-refreshing

For a website like www.example.com/path/to/index.html, you need to try a <HashRouter>.

For a website like www.example.com, <BrowserRouter> might work. The server like Nginx needs an extra config for proper renders after refreshing non-root pages.

location / {
   try_files $uri /index.html;
}
leaf
  • 1,624
  • 11
  • 16
0

You don't have to use HashRouter.

Just configure your static web server to serve index.html for all the routes that you've defined. If you're using Nginx for example, see this example config file. If you're using Apache or Express, see this.

Mostafa Farzán
  • 899
  • 2
  • 11
  • 30
0

If you deploy your static site on DigitalOcean, you can specify all routes in the App Spec under Your App > Settings > App Spec.

Just add a path for each route to the file under static_sites > routes.

Each route will then be forwarded to your / route where it will be handled by react router.

More info: https://docs.digitalocean.com/products/app-platform/concepts/http-route/

eddex
  • 1,622
  • 1
  • 15
  • 37
0

I had the same problem and I solved it using this link here https://hostrain.in/help/deploy-host-react-app-in-cpanel/ step 5 or in your public_html folder, add a .htaccess file and add the following code and save

<IfModule mod_rewrite.c>

  RewriteEngine On
  RewriteBase /
  RewriteRule ^index\.html$ - [L]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_FILENAME} !-l
  RewriteRule . /index.html [L]

</IfModule>

Please note that the .htaccess file is hidden and you should enable show hidden files in the settings of the file manager. Happy coding!