Search code examples
reactjsnpmbuildreact-routervite

Vite + React.js with React-router-dom gives 404 Error on Page reload


This is my Package.json

{
  "name": "man_power",
  "version": "0.1.0",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview"
  },
  "dependencies": {
    "@ckeditor/ckeditor5-build-classic": "^35.4.0",
    "@ckeditor/ckeditor5-react": "^5.0.5",
    "@material-ui/core": "^4.12.4",
    "@tailwindcss/forms": "^0.5.2",
    "chart.js": "^3.8.0",
    "chartjs-adapter-moment": "^1.0.0",
    "moment": "^2.29.4",
    "react": "^18.2.0",
    "react-bootstrap": "^2.7.0",
    "react-dom": "^18.2.0",
    "react-flatpickr": "^3.10.13",
    "react-icons": "^4.7.1",
    "react-loading-skeleton": "^3.1.0",
    "react-router-dom": "^6.3.0",
    "react-select": "^5.7.0",
    "react-select-country-list": "^2.2.3",
    "react-transition-group": "^4.4.2",
    "validator": "^13.7.0",
    "sweetalert": "^2.1.2"
  },
  "devDependencies": {
    "@vitejs/plugin-react": "^2.0.0",
    "autoprefixer": "^10.4.7",
    "postcss": "^8.4.14",
    "tailwindcss": "^3.1.6",
    "vite": "^3.0.0"
  }
}

This is my vite.config.js:

import { defineConfig } from "vite";
import postcss from "./postcss.config.js";
import react from "@vitejs/plugin-react";

// https://vitejs.dev/config/
export default defineConfig({
  define: {
    "process.env": process.env,
  },
  css: {
    postcss,
  },
  plugins: [react()],
  resolve: {
    alias: [
      {
        find: /^~.+/,
        replacement: (val) => {
          return val.replace(/^~/, "");
        },
      },
    ],
  },
  build: {
    commonjsOptions: {
      transformMixedEsModules: true,
    },
  },
  server: {
    host: true,
  },
});

I am using

npm run build

it outputs dist folder which contains: enter image description here

I was trying to navigate to different pages with react-router-dom but when I refresh on a *domainName/dashboard * I get a 404 error on the server.

Check it out at:

https://manpower1.xpertsgroup.net/


Solution

  • The same issue brought me to this page. So, for any who may follow, the reason (quite obvious in hindsight) is explained here: https://create-react-app.dev/docs/deployment/#serving-apps-with-client-side-routing

    To quote:

    If you use routers that use the HTML5 pushState history API under the hood (for example, React Router with browserHistory), many static file servers will fail. For example, if you used React Router with a route for /todos/42, the development server will respond to localhost:3000/todos/42 properly, but an Express serving a production build as above will not.

    This is because when there is a fresh page load for a /todos/42, the server looks for the file build/todos/42 and does not find it. The server needs to be configured to respond to a request to /todos/42 by serving index.html. For example, we can amend our Express example above to serve index.html for any unknown paths: [...]

    In my case (Apache server), I solved it by adding the following .htaccess file to my root folder:

    Options -MultiViews
         RewriteEngine On
         RewriteCond %{REQUEST_FILENAME} !-f
         RewriteRule ^ index.html [QSA,L]
    

    But solutions for other scenarios are discussed under the link.

    Be aware, you may have to configure your server via your hosting provider to allow "RewriteEngine". In my case, the option was "mod_rewrite" (set to "on").