最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

node.js - Deploying React app to production returns "You need to enable JavaScript to run this app" - Stack Ov

programmeradmin8浏览0评论

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?

  1. In package.json adding a "homepage": ".",
  2. In manifest.json, Changing start URL "start_url": ".", to "start_url": "/",
  3. 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?

  1. In package.json adding a "homepage": ".",
  2. In manifest.json, Changing start URL "start_url": ".", to "start_url": "/",
  3. Adding a proxy server. I already have it enabled ever since I started deployment. "proxy": "http://localhost:5000"
Share Improve this question edited Sep 24, 2020 at 19:51 Matthew Francis asked Sep 23, 2020 at 18:28 Matthew FrancisMatthew Francis 7403 gold badges11 silver badges27 bronze badges 4
  • 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
Add a ment  | 

3 Answers 3

Reset to default 0

I 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"));
    });

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论