'React Serve Build Routes showing 404 after build for production
Being stuck for about 4 hours trying to search for the solution but I gave up.
Have a React Application that works fine locally using
npm start
All the routes work fine, etc etc.
Then, I'm going to produce the production files by doing
npm run build
That creates the build files.
Then I serve it using the following
export PORT=5000 && serve -l 5000 build
Then, I go to the browser on localhost:5000, and the home page loads, but the rest of the application gives me a 404!
I have followed all the solutions I found and nothing. These are the key files I believe are involved.
public/manifest.json
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": "./index.html",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}
public/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta name="description" content="Web site created to display mnp tables" />
<link rel="stylesheet" href="https://pro.fontawesome.com/releases/v5.10.0/css/all.css"
integrity="sha384-AYmEC3Yw5cVb3ZcuHtOA93w35dYTsvhLPVnYs9eStHfGJvOvKxVfELGroGkvsg+p" crossorigin="anonymous" />
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP&family=Roboto&display=swap" rel="stylesheet">
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<title>SMS MNP</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>
package.json
{
"name": "client",
"proxy": "http://localhost:3000/",
"version": "0.1.0",
"private": true,
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^1.2.35",
"@fortawesome/free-solid-svg-icons": "^5.15.3",
"@fortawesome/react-fontawesome": "^0.1.14",
"@testing-library/jest-dom": "^5.11.10",
"@testing-library/react": "^11.2.6",
"@testing-library/user-event": "^12.8.3",
"bootstrap": "^5.0.1",
"build": "^0.1.4",
"cors": "^2.8.5",
"cross-env": "^7.0.3",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-js-pagination": "^3.0.3",
"react-loader-spinner": "^5.1.3",
"react-router-dom": "^5.2.0",
"react-scripts": "4.0.3",
"react-toastify": "^8.2.0",
"serve": "^12.0.0",
"web-vitals": "^1.1.1"
},
"scripts": {
"start": "export PORT=5000 && react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
src/App.js
import React, { useEffect, useState, useContext } from "react";
import Home from "./components/Home/Home.js";
import Nav from "./components/Header/Nav.js";
import "./css/table.css";
import { BrowserRouter as Router, Route, Switch, Redirect } from "react-router-dom";
import { AuthContext } from "../src/components/useContext/AuthContext.js";
import Footer from "./components/Footer/Footer";
import RenderTable from "./components/Home/RenderTable.js";
import RenderViews from "./components/Views/RenderViews";
import { toast } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
import Register from "./components/Header/Register.js";
import Login from "./components/Header/Login.js";
toast.configure()
function App() {
const [dropdownOptions, setDropdownOptions] = useState([]);
const [dropdownOptionsView, setDropdownOptionsView] = useState([]);
const [dropdownOptionsViewClient, setDropdownOptionsViewClient] = useState([]);
const { isAuthenticated, setIsAuthenticated } = useContext(AuthContext)
const checkAuthenticated = async () => {
try {
const res = await fetch("/auth/verify", {
method: "POST",
headers: { token: localStorage.token }
});
const parseRes = await res.json();
parseRes === true ? setIsAuthenticated(true) : setIsAuthenticated(false);
} catch (err) {
console.error(err.message);
}
};
const getTableNames = async () => {
try {
const res = await fetch('/tables/tablename', {
method: "GET",
headers: { token: localStorage.token }
});
const parseData = await res.json();
setDropdownOptions(parseData.filter(data => !data.includes("obs") && !data.includes("adm") && !data.includes("tst")));
} catch (err) {
console.error(err.message);
}
};
const getViews = async () => {
try {
const res = await fetch('/views/viewname', {
method: "GET"
});
const data = await res.json();
// if(!isAuthenticated){
setDropdownOptionsView(data.filter(data => data))
setDropdownOptionsViewClient(data.filter(data => data))
// else {
// setDropdownOptionsView(data.filter(data => data.includes("VW")))}
} catch (err) {
console.error(err.message);
}
};
useEffect(() => {
checkAuthenticated();
getTableNames()
getViews()
// console.log(dropdownOptionsViewClient)
}, [])
// useEffect(() => {
// fetch('/views/viewname')
// .then((res) => res.json())
// .then((data) => setDropdownOptionsView(data.filter(data => !data.includes("obs")))
// )
// }, [])
return (
<Router>
<Nav dropdownOptions={dropdownOptions} dropdownOptionsView={dropdownOptionsView} dropdownOptionsViewClient={dropdownOptionsViewClient} />
<Switch>
<Route exact path="/" render={() => (
<div className="container">
<div className="row">
<div className="col">
<Home isAuthenticated={isAuthenticated} data={dropdownOptions} dataView={dropdownOptionsView} />
</div>
</div>
</div>)} />
<Route
exact path="/tables/:name"
render={() => (
<RenderTable />
)} />
<Route
exact path="/views/:view"
render={() => (
<RenderViews />
)} />
<Route
exact path="/auth/login"
render={() => !isAuthenticated ? <Login isAuthenticated={isAuthenticated} /> : <Redirect to="/" />} />
<Route
exact path="/auth/register"
render={() => !isAuthenticated ? <Register isAuthenticated={isAuthenticated} /> : <Redirect to="/" />} />
</Switch>
<Footer />
</Router>
);
}
export default App;
src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import 'bootstrap/dist/css/bootstrap.css'
import { PageProvider } from "./components/useContext/PageContext";
import { DropProvider } from "./components/useContext/DropContext";
import { DropViewProvider } from "./components/useContext/DropViewContext";
import { ShowProvider } from "./components/useContext/ShowContext";
import { EditProvider } from "./components/useContext/EditContext";
import { SearchProvider } from './components/useContext/SearchContext';
import { SortProvider } from "./components/useContext/SortContext";
import { UpdateProvider } from './components/useContext/UpdateContext';
import { AuthProvider } from './components/useContext/AuthContext';
import { BrowserRouter as Router } from "react-router-dom";
//import provider to use context
ReactDOM.render(
<React.StrictMode>
<PageProvider>
<DropProvider>
<DropViewProvider>
<ShowProvider>
<EditProvider>
<SearchProvider>
<UpdateProvider>
<SortProvider>
<AuthProvider>
<Router>
<App />
</Router>
</AuthProvider>
</SortProvider>
</UpdateProvider>
</SearchProvider>
</EditProvider>
</ShowProvider>
</DropViewProvider>
</DropProvider>
</PageProvider>
</React.StrictMode>,
document.getElementById('root')
);
reportWebVitals();
PLEASE HELP!
PS: This is not an application I wrote. It was given to me after the person in charge left.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
