服务器上的 Express 静态文件未正确加载但 React 前端加载正确?

Posted

技术标签:

【中文标题】服务器上的 Express 静态文件未正确加载但 React 前端加载正确?【英文标题】:Express Static files on server not loading correctly but React Front end is loading correctly? 【发布时间】:2019-05-15 04:28:44 【问题描述】:

我有一个使用 Node/Express 为我的服务器服务的 ReactJS 项目。在我的前端(React)上服务端口 3312,在我的服务器上服务端口(5000)。当我通过端口 3312 加载前端时,一切看起来都很好,并且我的反应路由器路由工作正常。 (我的 api 的工作一切都很棒)。但是,当我尝试提供静态文件并查看是否通过我的服务器(端口 5000)获得相同的结果时,我只能看到页面上的样式。 (我有背景颜色)我没有看到任何静态文件应该提供的 html

当我查看 localhost:5000 时,控制台中没有任何错误。但是,我的 css 样式正确显示在页面上(因为我的身体上设置了背景颜色)。但是,我看不到任何显示 html 代码的前端 React。我进入我的 index.html 文件并在根 div 中进行了一个简单的测试,它正在显示,但我不明白为什么我的 React 代码没有显示在我的服务器上。

我很可能认为问题在于没有为我的图像或 React Router 代码提供服务的快速静态文件。我还应该注意,我没有使用 create-react-app 我正在使用 webpack dev server react no cli。

另外,我没有使用 create-react-app 我没有为自定义 webpack 使用 cli。

这是我的代码:

(节点服务器)

const express = require("express");
const path = require("path");
const router = express.Router();

const app = express();
const port = 5000;

// Serve static files on server
app.use("/public", express.static(__dirname + "/../public"));

app.get("*", function(request, response) 
  response.sendFile(path.join(__dirname + "/../public/index.html"));
);

if (app.get("env") === "development") 
  app.listen(port, () => 
    console.log(`Server started on port $port`);
  );
 else 
  app.listen(port, "171.33.4.126", () => 
    console.log(`Server started on port $port`);
  );

routes.js

import React from "react";

import  BrowserRouter as Router, Route, Switch  from "react-router-dom";

import HomePage from "./components/homepage";
import AboutPage from "./components/aboutpage";
import Contactpage from "./components/contactpage";

export default (
  <Router>
    <div>
      <Switch>
        <Route exact path="/" component=Landingpage />
        <Route exact path="/about" component=AboutPage />
        <Route exact path="/contact" component=Contactpage />
      </Switch>
    </div>
  </Router>
);

index.js

import React,  Component  from "react";
import ReactDOM from "react-dom";

import  BrowserRouter as Router, Route, Link  from "react-router-dom";
import Routes from "./routes";

ReactDOM.render(<div>Routes</div>, document.getElementById("root"));

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <link
      href="/public/assets/css/styles.css"
      rel="stylesheet"
      type="text/css"
    />
    <title>Site</title>
  </head>

  <body>
    <div id="root"></div>
  </body>
</html>

Webpack 配置开发

const webpack = require("webpack");
const path = require("path");
// const HtmlWebPackPlugin = require("html-webpack-plugin");
const BrowserSyncPlugin = require("browser-sync-webpack-plugin");

module.exports = 
  devServer: 
    historyApiFallback: true,
    port: 3312,
    proxy: 
      "/api": "http://localhost:5000"
    
  ,
  entry: ["babel-polyfill", __dirname + "/src/index.js"],
  output: 
    path: path.join(__dirname, "/public"),
    filename: "bundle.js",
    publicPath: "/"
  ,
  module: 
    rules: [
      
        test: /\.jsx?$/,
        exclude: /node_modules/,
        use: 
          loader: "babel-loader",
          query: 
            presets: ["react", "env", "stage-0"]
          
        
      ,
      
        test: /\.css$/,
        use: [
           loader: "style-loader" ,
           loader: "css-loader" ,
           loader: "sass-loader" 
        ]
      
    ]
  ,
  plugins: [
    // new HtmlWebPackPlugin(
    //   template: "./public/index.html"
    // ),
    new BrowserSyncPlugin(
      host: "localhost",
      port: 3312,
      files: [
        "./public/*.html",
        "./public/assets/scss/*.scss",
        "./public/assets/variables/*.scss",
        "./public/assets/mixins/*.scss",
        "./public/assets/reset/*.scss"
      ],
      proxy: "http://localhost:3312/"
    )
  ]
;

这是我的文件夹结构的截图:

控制台网络状态截图:

【问题讨论】:

console.log(__dirname + "/../public")` 说了什么?我敢打赌问题出在路径上 上传了我的文件夹结构截图 记录控制台返回C:\Users\myusername\Desktop\newrootportfolio\server/../public OK ...我的路径似乎是正确的...您可以检查 Web 控制台中的网络选项卡以查看您从服务器收到的内容吗? 我在 localhost 5000(服务器)中附加了网络截图 localhost 3312(客户端)工作正常我可以看到 html css 但在我的服务器上我只能看到 css 而不是 html 【参考方案1】:

您的反应代码没有显示,因为index.html 不包括它。 public/bundle.js 是您转译的反应代码吗?如果是这样,将以下行添加到index.html,紧跟在&lt;div id="root"&gt;&lt;/div&gt; 之后:

<script src="/public/bundle.js"></script>

如果不是,则将src指向的路径改成正确的。

您可以很好地查看您的 css 样式,因为您已经在 index.html 中包含了这些样式。

更新:几点基于您的 webpack 配置:

将运行 webpack-dev-server 的端口更改为 3000。您还必须将 BrowserSyncPlugin 的代理更改为 http://localhost:3000/。然后您可以在浏览器中访问localhost:3312,请求将被代理到运行在端口 3000 上的 webpack-dev-server。

如果我错了,请纠正我,但你还没有完整地发布你的index.html。我猜你在.html 文件中的某处已经有一条看起来像&lt;script src="/bundle.js"&gt;&lt;/script&gt; 的行——根据你的最新评论,它似乎是由HtmlWebPackPlugin 添加的。 webpack-dev-server 服务于bundle.js/,你在webpack 的output 选项中指定的publicPath。只要您通过localhost:3312localhost:3000 访问您的网站,此方法就可以正常工作。但是,在端口 5000 上运行的 express.js 服务器不知道 webpack-dev-server 正在为 bundle.js / 提供服务;因此,当您转到 localhost:5000 时,您最终看不到任何反应代码。至于样式,您已经通过/public/assets/css 正确地为它们提供服务,express.js 服务器可以理解,因为您已在此行中指定:app.use("/public", express.static(__dirname + "/../public"))。解决方案是将&lt;script src="/bundle.js"&gt;&lt;/script&gt; 文件中的.html 行更改为:

<script src="http://localhost:3312/bundle.js"></script>

另外,在 webpack 的输出选项中,将 publicPath 更改为 http://localhost:3312/。现在,只要你有 webpack-dev-server 运行(使用BrowserSyncPlugin),你就可以访问 你的网站localhost:5000 和你的bundle.js 文件应该是 服务很好。

尝试以下方法:

Webpack 配置

module.exports = 
    devServer: 
        contentBase: path.join(__dirname, "/public"),
        historyApiFallback: true,
        port: 3000,
        proxy: 
            "/api": "http://localhost:5000"
        
    ,
    entry: ["babel-polyfill", __dirname + "/src/index.js"],
    output: 
        path: path.join(__dirname, "/public"),
        filename: "bundle.js",
        publicPath: "http://localhost:3312/"
    ,
    module: 
        rules: [
            
                test: /\.jsx?$/,
                exclude: /node_modules/,
                use: 
                    loader: "babel-loader",
                    query: 
                        presets: ["react", "env", "stage-0"]
                    
                
            ,
            
                test: /\.css$/,
                use: [
                     loader: "style-loader" ,
                     loader: "css-loader" ,
                     loader: "sass-loader" 
                ]
            
        ]
    ,
    plugins: [
        new BrowserSyncPlugin(
            host: "localhost",
            port: 3312,
            files: [
                "./public/*.html",
                "./public/assets/scss/*.scss",
                "./public/assets/variables/*.scss",
                "./public/assets/mixins/*.scss",
                "./public/assets/reset/*.scss"
            ],
            proxy: "http://localhost:3000/"
        )
    ]
;

index.html

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <meta name="theme-color" content="#000000" />
        <link
            href="/assets/css/styles.css"
            rel="stylesheet"
            type="text/css"
        />
        <title>Site</title>
    </head>
    <body>
        <div id="root"></div>
        <script src="http://localhost:3312/bundle.js"></script>
    </body>
</html>

【讨论】:

对于我的自定义 webpack 配置,我使用 webpack 插件来包含我相信的包含 bundle.js 的 index.html 文件? @Jorden 你能把你的 webpack 配置添加到你的问题中吗?我假设您指的是HtmlWebpackPlugin。如果是这种情况,并且如果index.html 是输出,那么它显然不包括bundle.js。尝试手动添加;那么它应该可以工作了。 您也可以通过查看您发布的屏幕截图来判断;没有对 /public/bundle.js 资产的请求,这意味着它不在您的快速后端发送给客户端的 html 中。 但奇怪的是,当我在浏览器中预览源代码时,包含 /bundle.js 但我在文件中看不到它。不过我会发布我的文件的屏幕截图。 @Jorden 我不确定你最后一句话的意思,但我已经更新了我的答案。我希望这会有所帮助。【参考方案2】:

抱歉,问题似乎出在 index.js 中。将Routes 更改为&lt;Routes /&gt;

import React,  Component  from "react";
import ReactDOM from "react-dom";

import  BrowserRouter as Router, Route, Link  from "react-router-dom";
import Routes from "./routes";

ReactDOM.render(<div><Routes/></div>, document.getElementById("root"));

您在 routes.js 中遇到了另一个问题。像这样导出一个组件

import React from "react";

import  BrowserRouter as Router, Route, Switch  from "react-router-dom";

import HomePage from "./components/homepage";
import AboutPage from "./components/aboutpage";
import Contactpage from "./components/contactpage";

// make this a component
export default ()=>(
  <Router>
      <Switch>
        <Route exact path="/" component=Landingpage />
        <Route exact path="/about" component=AboutPage />
        <Route exact path="/contact" component=Contactpage />
      </Switch>
  </Router>
);

【讨论】:

@Jorden 修复了吗?问题是您没有渲染 Routes 组件,因此不会显示任何内容 不一样的效果。我检查了前端,控制台返回:Element type is invalid expected a string (for built in components) or a class/function (for composite components) but got object. 我在您的 React 代码中看到另一个问题,让我更新答案 您在 routes.js 中导出的不是组件。这就是您收到该错误的原因 快递方面没问题。看起来你在使用 React 时遇到了一些问题

以上是关于服务器上的 Express 静态文件未正确加载但 React 前端加载正确?的主要内容,如果未能解决你的问题,请参考以下文章

NodeJS + Express 提供的 HTML 文件未加载 js 文件?

托管在通过 Azure Front Door 访问的存储帐户上的静态网站未正确加载

django+nginx 部署未正确加载静态文件

Express 发送带参数的静态 html 文件时路径不正确

为啥express要指定静态资源托管

媒体文件未在模板中正确加载 (HTML <img>)。静态文件/图像正常工作