如何在服务器端使用React渲染图像?

17

我应该如何在React中使用服务器端渲染呈现图像和css文件?

这是我的服务器代码:

const express = require('express')
const router = express.Router()
const ReactDOM = require('react-dom/server');

import Master from '../../../client/Master'

router.get('/', (req, res) => {
    res.render('test.html', {reactOutput: ReactDOM.renderToString(<Master/>)});
});

主组件:

import React from "react";
import Intro from "./pages/Intro";
import Footer from "./components/Footer";
import Header from "./components/Header";

export default class Master extends React.Component {
    constructor() {
        super();
        this.state = {appStatus: 'INTRO'}
    }

    render() {
        let layout;
        switch (this.state.appStatus) {
            case "INTRO":
                layout = <Intro/>;
        }

        return (
            <div>
                <Header/>
                {layout}
                <Footer/>
            </div>
        )
    }
}

但是,当我使用babel运行服务器时,我遇到了这个错误:

/assets/img/logo.png: 意外的字符 '?' (1:0)

这是Header组件,它尝试要求Logo。

import React from "react";
**import logo  from '../../assets/img/logo.png';**

export default class Header extends React.Component {
    constructor() {
        super();
    }

    render() {
        return (
            <nav class="navbar navbar-default">
                <div class="container-fluid">
                    <div class="navbar-header">
                        <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                            <span class="sr-only">Toggle navigation</span>
                            <span class="icon-bar"></span>
                            <span class="icon-bar"></span>
                            <span class="icon-bar"></span>
                        </button>
                        <a class="navbar-brand" href="#">**<img width="250" src={logo} alt=""/></a>**
                    </div>


                </div>
            </nav>
        );
    }
}

但是对于客户端的webpack它可以正常工作。


我知道这已经过时了,但你最终解决了吗?我也遇到了同样的问题。 - Fenda
2个回答

6
你需要为服务器编写单独的webpack配置文件。
  1. Install this module to exclude node_modules:

    npm install --save webpack-node-externals 
    
  2. Create a separate webpack config for your server:

    module.exports = {    
      const path = require('path')
      const nodeExternals = require('webpack-node-externals')
    
      context: path.resolve(__dirname, 'directory of your server file'),
      entry: ['./filename of your server file'],
      output: {
        path: path.join(__dirname, 'directory of your bundled file'),
        filename: 'filename of your bundled file'
      },
      target: 'node',
      externals: [nodeExternals()],
      module: {
        rules: [
          {
            test: /\.(jpe?g|png|gif|svg|ico)$/i,
            use: 'url-loader?limit=8192'
          }
        ]
      }
    }
    
  3. Here's an example server webpack.config.js:

    module.exports = {    
      const path = require('path')
      const nodeExternals = require('webpack-node-externals')
    
      context: path.resolve(__dirname, 'src'),
      entry: ['./index.js'],
      output: {
        path: path.join(__dirname, 'dist'),
        filename: 'bundle.js'
      },
      target: 'node',
      externals: [nodeExternals()],
      module: {
        rules: [
          {
            test: /\.(jpe?g|png|gif|svg|ico)$/i,
            use: 'url-loader?limit=8192'
          }
        ]
      }
    }
    
  4. If using the above webpack.config.js example, run webpack then the compiled server file:

    webpack
    node dist/bundle.js
    

对我来说不起作用。结果是输出路径上的图像和寻找它的src为'src='2013068ae43bfc8883afa52e781eef49.jpg'。但如果不在根路由上,则会解析为http://localhost:3000/receitas/2013068ae43bfc8883afa52e781eef49.jpg,这不是文件位置。 - RobertoOSantos
当我尝试获取此URL http://localhost:3000/receitas/2013068ae43bfc8883afa52e781eef49.jpg 或者这个 http://localhost:3000/2013068ae43bfc8883afa52e781eef49.jpg 时,结果不是图像也不是 NOT FOUND。而是 index.js 服务器端呈现的内容。 - RobertoOSantos

0
以上答案可能已经过时或存在一些问题。这里是 webpack 5 的更新答案。它可以从它们各自的文件夹中导入字体和图像。
const path = require("path");

module.exports = {
  target: "node",
  entry: {
    server: "./server.js"
  },
  output: {
    path: path.join(__dirname),
    filename: "[name]-packed.js",
  },
  module: {
    rules: [
      {
        test: /\.(jpe?g|png|gif|svg|ico)$/i,
        use: [
          {
            loader: 'file-loader',
            options: {
              name: '[name].[ext]',
              outputPath: 'img/'
            }
          }
        ]
      },
      {
                test: /\.(js|jsx)$/,
                exclude: /node_modules/,
                loader: "babel-loader"
            },
      {
        test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
        use: [
          {
            loader: 'file-loader',
            options: {
              name: '[name].[ext]',
              outputPath: 'fonts/'
            }
          }
        ]
      }
    ],
  },
};

只是想提一下,在WP5中file-loader已经被弃用了 - https://github.com/webpack-contrib/file-loader#file-loader - WP5指出已弃用的功能将被删除。所以我不确定行为是否符合预期 - https://webpack.js.org/migrate/5/#make-sure-your-build-has-no-errors-or-warnings - nsun

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接