Problem
I have an axios call at "/artists", that gets a list of artists returned as an array of JSON. It works in development. However, in production it outputs an HTML element that says You need to enable Javascript because the data returned from "/artists" is undefined (proof of it below):
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="./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 using create-react-app" />
<link rel="apple-touch-icon" href="./logo192.png" />
<link rel="manifest" href="./manifest.json" />
<title>React App</title>
<link href="./static/css/main.5eece21d.chunk.css" rel="stylesheet" />
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<script>
!(function (e) {
function t(t) {
for (var n, f, i = t[0], l = t[1], p = t[2], c = 0, s = []; c < i.length; c++) (f = i[c]), Object.prototype.hasOwnProperty.call(o, f) && o[f] && s.push(o[f][0]), (o[f] = 0);
for (n in l) Object.prototype.hasOwnProperty.call(l, n) && (e[n] = l[n]);
for (a && a(t); s.length; ) s.shift()();
return u.push.apply(u, p || []), r();
}
function r() {
for (var e, t = 0; t < u.length; t++) {
for (var r = u[t], n = !0, i = 1; i < r.length; i++) {
var l = r[i];
0 !== o[l] && (n = !1);
}
n && (u.splice(t--, 1), (e = f((f.s = r[0]))));
}
return e;
}
var n = {},
o = { 1: 0 },
u = [];
function f(t) {
if (n[t]) return n[t].exports;
var r = (n[t] = { i: t, l: !1, exports: {} });
return e[t].call(r.exports, r, r.exports, f), (r.l = !0), r.exports;
}
(f.m = e),
(f.c = n),
(f.d = function (e, t, r) {
f.o(e, t) || Object.defineProperty(e, t, { enumerable: !0, get: r });
}),
(f.r = function (e) {
"undefined" != typeof Symbol && Symbol.toStringTag && Object.defineProperty(e, Symbol.toStringTag, { value: "Module" }), Object.defineProperty(e, "__esModule", { value: !0 });
}),
(f.t = function (e, t) {
if ((1 & t && (e = f(e)), 8 & t)) return e;
if (4 & t && "object" == typeof e && e && e.__esModule) return e;
var r = Object.create(null);
if ((f.r(r), Object.defineProperty(r, "default", { enumerable: !0, value: e }), 2 & t && "string" != typeof e))
for (var n in e)
f.d(
r,
n,
function (t) {
return e[t];
}.bind(null, n)
);
return r;
}),
(f.n = function (e) {
var t =
e && e.__esModule
? function () {
return e.default;
}
: function () {
return e;
};
return f.d(t, "a", t), t;
}),
(f.o = function (e, t) {
return Object.prototype.hasOwnProperty.call(e, t);
}),
(f.p = "./");
var i = (this.webpackJsonpspotify = this.webpackJsonpspotify || []),
l = i.push.bind(i);
(i.push = t), (i = i.slice());
for (var p = 0; p < i.length; p++) t(i[p]);
var a = l;
r();
})([]);
</script>
<script src="./static/js/2.2cc1353a.chunk.js"></script>
<script src="./static/js/main.0515e6b9.chunk.js"></script>
</body>
This error appears because in my action creator:
export const fetchArtists = () => async (dispatch: Dispatch) => {
const response = await axios.get<Artist[]>("/artists");
console.log(response);
dispatch<FetchArtistsAction>({
type: ActionTypes.FETCH_ARTISTS,
payload: response.data,
});
};
console.log(response) output in production mode :
console.log(response) output in development mode:
My site
/
The page would load, then it will give you a blank page because of the /artists route call. It will you the production output above, causing the error.
Backend code
My src/backend/artistRoutes.ts
router.get("/", async (req: RequestWithBody, res: Response) => {
const artists = await Artists.find({});
res.send(artists);
});
My src/backend/index.ts, which generates the src/backend/build when piled:
.....
.....
mongoose.connect(process.env.mongoURI, { useNewUrlParser: true });
//Models
require("./models/Artists");
//Routes
app.use("/artists", artistsRoutes);
const PORT = process.env.PORT || 5000;
//Production
const path = require("path");
if (process.env.NODE_ENV === "production") {
app.use(express.static(path.join(__dirname, "../../../build")));
app.get("*", function (req, res) {
res.sendFile(path.join(__dirname, "../../../build"));
});
}
app.listen(PORT);
Overview of my project's folder structure:
I have set up my production environment variables in Vercel, my hosting site:
Other solutions I've tried from other posts with no avail:
I am getting error in console "You need to enable JavaScript to run this app." reactjs
Why won't React production build run on the browser?
- In package.json adding a
"homepage": ".",
- In manifest.json, Changing start URL
"start_url": ".",
to"start_url": "/",
- Adding a proxy server. I already have it enabled ever since I started deployment.
"proxy": "http://localhost:5000"
Problem
I have an axios call at "/artists", that gets a list of artists returned as an array of JSON. It works in development. However, in production it outputs an HTML element that says You need to enable Javascript because the data returned from "/artists" is undefined (proof of it below):
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="./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 using create-react-app" />
<link rel="apple-touch-icon" href="./logo192.png" />
<link rel="manifest" href="./manifest.json" />
<title>React App</title>
<link href="./static/css/main.5eece21d.chunk.css" rel="stylesheet" />
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<script>
!(function (e) {
function t(t) {
for (var n, f, i = t[0], l = t[1], p = t[2], c = 0, s = []; c < i.length; c++) (f = i[c]), Object.prototype.hasOwnProperty.call(o, f) && o[f] && s.push(o[f][0]), (o[f] = 0);
for (n in l) Object.prototype.hasOwnProperty.call(l, n) && (e[n] = l[n]);
for (a && a(t); s.length; ) s.shift()();
return u.push.apply(u, p || []), r();
}
function r() {
for (var e, t = 0; t < u.length; t++) {
for (var r = u[t], n = !0, i = 1; i < r.length; i++) {
var l = r[i];
0 !== o[l] && (n = !1);
}
n && (u.splice(t--, 1), (e = f((f.s = r[0]))));
}
return e;
}
var n = {},
o = { 1: 0 },
u = [];
function f(t) {
if (n[t]) return n[t].exports;
var r = (n[t] = { i: t, l: !1, exports: {} });
return e[t].call(r.exports, r, r.exports, f), (r.l = !0), r.exports;
}
(f.m = e),
(f.c = n),
(f.d = function (e, t, r) {
f.o(e, t) || Object.defineProperty(e, t, { enumerable: !0, get: r });
}),
(f.r = function (e) {
"undefined" != typeof Symbol && Symbol.toStringTag && Object.defineProperty(e, Symbol.toStringTag, { value: "Module" }), Object.defineProperty(e, "__esModule", { value: !0 });
}),
(f.t = function (e, t) {
if ((1 & t && (e = f(e)), 8 & t)) return e;
if (4 & t && "object" == typeof e && e && e.__esModule) return e;
var r = Object.create(null);
if ((f.r(r), Object.defineProperty(r, "default", { enumerable: !0, value: e }), 2 & t && "string" != typeof e))
for (var n in e)
f.d(
r,
n,
function (t) {
return e[t];
}.bind(null, n)
);
return r;
}),
(f.n = function (e) {
var t =
e && e.__esModule
? function () {
return e.default;
}
: function () {
return e;
};
return f.d(t, "a", t), t;
}),
(f.o = function (e, t) {
return Object.prototype.hasOwnProperty.call(e, t);
}),
(f.p = "./");
var i = (this.webpackJsonpspotify = this.webpackJsonpspotify || []),
l = i.push.bind(i);
(i.push = t), (i = i.slice());
for (var p = 0; p < i.length; p++) t(i[p]);
var a = l;
r();
})([]);
</script>
<script src="./static/js/2.2cc1353a.chunk.js"></script>
<script src="./static/js/main.0515e6b9.chunk.js"></script>
</body>
This error appears because in my action creator:
export const fetchArtists = () => async (dispatch: Dispatch) => {
const response = await axios.get<Artist[]>("/artists");
console.log(response);
dispatch<FetchArtistsAction>({
type: ActionTypes.FETCH_ARTISTS,
payload: response.data,
});
};
console.log(response) output in production mode :
console.log(response) output in development mode:
My site
https://spotify-eight.vercel.app/
The page would load, then it will give you a blank page because of the /artists route call. It will you the production output above, causing the error.
Backend code
My src/backend/artistRoutes.ts
router.get("/", async (req: RequestWithBody, res: Response) => {
const artists = await Artists.find({});
res.send(artists);
});
My src/backend/index.ts, which generates the src/backend/build when piled:
.....
.....
mongoose.connect(process.env.mongoURI, { useNewUrlParser: true });
//Models
require("./models/Artists");
//Routes
app.use("/artists", artistsRoutes);
const PORT = process.env.PORT || 5000;
//Production
const path = require("path");
if (process.env.NODE_ENV === "production") {
app.use(express.static(path.join(__dirname, "../../../build")));
app.get("*", function (req, res) {
res.sendFile(path.join(__dirname, "../../../build"));
});
}
app.listen(PORT);
Overview of my project's folder structure:
I have set up my production environment variables in Vercel, my hosting site:
Other solutions I've tried from other posts with no avail:
I am getting error in console "You need to enable JavaScript to run this app." reactjs
Why won't React production build run on the browser?
- In package.json adding a
"homepage": ".",
- In manifest.json, Changing start URL
"start_url": ".",
to"start_url": "/",
- Adding a proxy server. I already have it enabled ever since I started deployment.
"proxy": "http://localhost:5000"
- 1 You can try to add index.html as a third argument res.sendFile(path.resolve(__dirname, '../../../build', 'index.html')) and you can try to play with path "../../"(or "../") maybe production deploy do something unpredictable with paths... – Alexey Nazarov Commented Sep 23, 2020 at 19:50
- Thanks for the response @Alexey, I;ve tried it with ../, ../../ , ../../../ and ../../../../ but it does not work! – Matthew Francis Commented Sep 23, 2020 at 20:52
- 3 Found solution to this? I am also stuck – Syed Danial Commented May 14, 2021 at 15:39
- 1 Hi, did you find a solution for this? – Habib Rehman Commented Mar 26, 2022 at 19:24
3 Answers
Reset to default 0I assume you serve react static files using nginx or apache.
If so, try look in /etc/nginx/sites-enabled/the-config-file
, for react it usually has this line:
try_files $uri /index.html;
What it does is, if someone access https://spotify-eight.vercel.app/artists, try serve https://spotify-eight.vercel.app/artists/index.html, if not found serve rootPath/index.html. I think thats what is happening.
I suggest serve the api endpoint in another port other than :80 so static files and endpoints can be differentiate easily. Dont change the nginx config try_files directive because your react app wont serve paths correctly otherwise.
Introduction
I was struggling with the same issue for days. It seems like there is a problem (also lack of documentation) on how to integrate Vercel and React backend. Below solution is working for my Vercel application.
I am simply posting the solution from the original author who seems to have fixed their React application without updating this question.
Solution
Create a separate React application for the backend. Make sure to start with the backend and then add the frontend if it is still needed. You can follow this YouTube as a template and move all backend files inside it. Then, add a proxy from your frontend project to the newly created backend application to make it work in production.
Proof
Click on the https://spotify-eight.vercel.app/ and right click to inspect the webpage. Go under Network, check Preserve logs and Fetch/XHR.
Refresh the page. You should now see a request called artists. Under Headers the requested URL is https://spotify-backend.vercel.app/artists. The author of the question has fixed the issue by creating another Vercel application. Visit the URL if you want to make sure the backend application is accessible from outside.
Have you tried:
app.get("*", function (req, res, next) {
if (req.url.startsWith("/artists")) return next();
res.sendFile(path.join(__dirname, "../../../build"));
});