React Router - Route not working on Refresh in webpack production build

Viewed 294

I am currently trying to deploy my react app created with Webpack. I am using react router for routing and everything works fine in dev mode, but when I am creating the production version of my web app routing works too at first but when I refresh the page I get the following

Not found

I also don't know if this is caused by webpack.

This is my webpack.common.js (settings that are similar between production and dev version)

const path = require("path");

module.exports = {
  context: __dirname,
  entry: {
    main: "./src/index.js",
    vendor: "./src/vendor.js"
  },
  module: {
    rules: [
      {
        test: /\.html$/,
        use: ["html-loader"]
      },
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader",
        },
      },
      {
        test: /\.(jpg|png)$/,
        use: {
          loader: "file-loader",
          options:{
            name: "[name].[hash].[ext]",
            outputPath:"imgs"
          }
        },
      },
      {
        test:/\.svg$/,
        use: ['@svgr/webpack']
      },
        
      {
        test: /\.(ttf|eot|woff|woff2)$/,
        exclude: /node_modules/,
        use: {
          loader: "url-loader",
        },
      },
    ],
  },
};

This is my webpack.prod.js (production version of webpack):

const path = require("path");
const common = require("./webpack.common");
const { merge } = require("webpack-merge");
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const TerserPlugin = require("terser-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = merge(common, {
  context: __dirname,
  mode: "production",
  output: {
    path: path.resolve(__dirname, "dist"),
    publicPath: "/",
    filename: "bundle.[contentHash].js",
  },
  optimization: {
    minimizer:[
      new OptimizeCssAssetsPlugin(), new TerserPlugin()
    ]
  },
  module: {
    rules: [
      {
        test: /\.s[ac]ss$/i,
        use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],
      },
    ],
  },
  plugins: [
    new CleanWebpackPlugin(),
    new MiniCssExtractPlugin({ filename: "[name].[contentHash].css" }),
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, "public/template.html"),
      // favicon: "./src/App/assets/Logo.png",
      filename: "index.html",
      minify:{
        removeAttributeQuotes: true,
        collapseWhiteSpaces: true,
        removeComments: true,
      }
    }),
  ],
})

This is the main react file that provides the routes:

import Projects from "./pages/Projects/projects.jsx";
import ContentSwitch from "./pages/Content/ContentSwitch/ContentSwitch.jsx";
import Contact from "./pages/Contact/contact.jsx";
import Foyer from "./pages/Foyer/foyer.jsx";
import Login from "./pages/Login/login.jsx";
import Error from "./pages/Error/error.js";
import UgBar from "./shared/bar/bar.jsx";
import "./scss/App.scss";
import React, {
  useRef,
  useState,
  useCallback,
  useLayoutEffect,
  useContext,
} from "react";

import { Route, Switch } from "react-router-dom";
import { AnimatePresence } from "framer-motion";
import { SearchProvider } from "./context/SearchContext.js";
import { BlurProvider } from "./context/BlurContext.js";

function App() {
  return (
    <div>
      <SearchProvider>
        <BlurProvider>
          <UgBar />
          <AnimatePresence>
            <Switch className="ug-switch">
              <Route exact path="/" component={Foyer}></Route>
              <Route path="/projects" component={Projects}></Route>
              <Route path="/content" component={ContentSwitch}></Route>
              <Route path="/contact" component={Contact}></Route>
              <Route path="/login" component={Login}></Route>
              <Route path="*" exact={true} component={Error}></Route>
            </Switch>
          </AnimatePresence>
        </BlurProvider>
      </SearchProvider>
    </div>
  );
}

export default App;

Thank you and stay safe!

1 Answers

What kind of server are you using?

I had this problem using nginx. In the sites-available file the line I had to fix was

try_files $uri $uri/ /index.html =404;

in the server block. Now it works.

Related