将 React 应用程序部署到生产环境返回“您需要启用 JavaScript 才能运行此应用程序”

Posted

技术标签:

【中文标题】将 React 应用程序部署到生产环境返回“您需要启用 JavaScript 才能运行此应用程序”【英文标题】:Deploying React app to production returns "You need to enable JavaScript to run this app" 【发布时间】:2021-01-10 00:32:47 【问题描述】:

问题

我在“/artists”有一个 axios 调用,它获取作为 JSON 数组返回的艺术家列表。它在开发中工作。但是,在生产中,它会输出一个 html 元素,上面写着 您需要启用 Javascript,因为从“/artists”返回的数据是未定义的(下面是它的证明):

<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>

出现此错误是因为在我的动作创建者中:

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) 在生产模式下输出:

console.log(response) 开发模式输出:

我的网站

https://spotify-eight.vercel.app/

页面将加载,然后由于 /artists 路由调用,它会给您一个空白页面。它会给你上面的生产输出,导致错误。

后端代码

我的 src/backend/artistRoutes.ts

router.get("/", async (req: RequestWithBody, res: Response) => 
    const artists = await Artists.find();
    res.send(artists);
);

我的src/backend/index.ts,编译时生成src/backend/build

.....
.....
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);

我的项目文件夹结构概览

我已经在我的托管站点 Vercel 中设置了我的生产环境变量

我在其他帖子中尝试过的其他解决方案均无济于事:

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?

    在 package.json 添加"homepage": ".", 在 manifest.json 中,将起始 URL "start_url": ".", 更改为 "start_url": "/", 添加代理服务器。自从我开始部署以来,我就已经启用了它。 "proxy": "http://localhost:5000"

【问题讨论】:

您可以尝试添加 index.html 作为第三个参数 res.sendFile(path.resolve(__dirname, '../../../build', 'index.html'))您可以尝试使用路径“../../”(或“../”),也许生产部署会使用路径做一些不可预测的事情...... 感谢@Alexey 的回复,我已经尝试使用 ../、../../、../../../ 和 ../../.. /../ 但它不起作用! 找到解决方案了吗?我也卡住了 【参考方案1】:

你试过了吗:

app.get("*", function (req, res, next) 
        if (req.url.startsWith("/artists")) return next();
        res.sendFile(path.join(__dirname, "../../../build"));
    );

【讨论】:

【参考方案2】:

我假设您使用 nginx 或 apache 提供 react 静态文件。 如果是这样,请尝试查看/etc/nginx/sites-enabled/the-config-file,对于反应它通常有这行:

  try_files $uri /index.html;

它的作用是,如果有人访问https://spotify-eight.vercel.app/artists,尝试服务https://spotify-eight.vercel.app/artists/index.html,如果没有找到服务rootPath/index.html。我认为这就是正在发生的事情。

我建议在 :80 以外的另一个端口提供 api 端点,以便可以轻松区分静态文件和端点。不要更改 nginx 配置 try_files 指令,否则您的反应应用程序将无法正确提供路径。

【讨论】:

感谢您的回复!但是,我没有使用 apache 或 nginx。我使用 Create React Ap 的 npm run build 来提供我的文件。

以上是关于将 React 应用程序部署到生产环境返回“您需要启用 JavaScript 才能运行此应用程序”的主要内容,如果未能解决你的问题,请参考以下文章

您需要启用 JavaScript 才能运行此应用程序。将 React 应用部署到 Firebase 后

你如何配置 Webpack 以清除生产缩小的 React 警告?

React:在没有构建的情况下运行生产

部署 create-react-app 时无法加载资源错误 404

使用 jenkins 进行持续部署

在 SQL Server 2005 中将不安全的程序集部署到生产环境