typescriptwebpackreact-routerreact-router-dom

Webpack React Router DOM build issue


I have a React+Typescript app with Webpack 5 configuration that was built from scratch. For routing I use React Router DOM 6.23.1. In development mode routing works as expected, but after I build the app components are not displayed. There are no errors in console. This happens only for components inside <Route>. For example, If I place <Home> component outside of <Routes>, it will be displayed.

What I tried and it didn't help: downgrading React Router DOM, adding "homepage": "." to package.json.

index.tsx

import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import App from "./App";
import { BrowserRouter } from "react-router-dom";

const rootElement = document.getElementById("root");

const root = createRoot(rootElement!);

root.render(
  <StrictMode>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </StrictMode>
);

App.tsx

import { Route, Routes } from "react-router-dom";
import GlobalStyle from "./globalStyles";
import { ApolloProvider } from "@apollo/client";
import { RecoilRoot } from "recoil";
import { Layout } from "./components/Layout";
import { Home } from "./components/pages/Home";
import { client } from "./lib/data";
import { Favorites } from "./components/pages/Favorites";
import { Tours } from "./components/pages/Tours";
import { About } from "./components/pages/About";

export default function App() {
  return (
    <main>
      <GlobalStyle />
      <RecoilRoot>
        <ApolloProvider client={client}>
          <Routes>
            <Route path="/" element={<Layout />}>
              <Route index element={<Home />} />
              <Route path="favorites" element={<Favorites />} />
              <Route path="tours" element={<Tours />} />
              <Route path="about" element={<About />} />
            </Route>
          </Routes>
        </ApolloProvider>
      </RecoilRoot>
    </main>
  );
}

webpack.config.ts

import path from "path";
import { Configuration } from "webpack";
import CopyWebpackPlugin from "copy-webpack-plugin";
import "webpack-dev-server";

const config: Configuration = {
  entry: "./src/index.tsx",
  module: {
    rules: [
      {
        test: /.tsx?$/,
        use: "ts-loader",
        exclude: /node_modules/,
      },
      {
        test: /\.css$/,
        use: ["style-loader", "css-loader"],
      },
    ],
  },
  resolve: {
    extensions: [".tsx", ".ts", ".js"],
  },
  output: {
    filename: "bundle.js",
    path: path.resolve(__dirname, "dist"),
    publicPath: "/",
  },
  devServer: {
    historyApiFallback: true,
    static: {
      directory: path.resolve(__dirname, "dist"),
    },
    compress: true,
    port: 8080,
  },
  plugins: [
    new CopyWebpackPlugin({
      patterns: [{ from: "public" }],
    }),
  ],
};

export default config;

tsconfig.json

{
  "compilerOptions": {
    "jsx": "react-jsx",
    "noImplicitAny": true,
    "target": "es5",
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true,
    "outDir": "./dist/",
    "moduleResolution": "node"
  },
  "include": ["**/*.ts", "**/*.tsx"]
}

Solution

  • For anyone facing this issue. I had to add vercel.json file:

    {
      "rewrites": [{ "source": "/(.*)", "destination": "/" }]
    }
    

    Also, I was missing Output directory in Vercel's Build & Development Settings. It should be dist in my case.

    Build & Development Settings