Рендеринг на стороне сервера не отображает библиотеку пользовательского интерфейса - PullRequest
0 голосов
/ 16 января 2019

Я пытаюсь реализовать рендеринг на стороне сервера для моего приложения. Раньше это был клиентский рендер, использующий ReactDom. В рендеринге на стороне клиента все работает нормально, но теперь, когда я делаю рендеринг на стороне сервера, ни одна из таблиц CSS и библиотек пользовательского интерфейса (Reactstrap + Material UI) не рендерится. Пользовательский интерфейс полностью сломался.

Я внедряю мой App.js (настоящую интерфейсную страницу со всем пользовательским интерфейсом) в мой html.js (шаблон)

Мой сервер:

import express from 'express';
import React from 'react';
import { renderToString } from 'react-dom/server'
import App from '../../src/App'
import Html from '../../src/html.js'
const app = express();

// console.log that your server is up and running
app.listen(3001, () => console.log(`Listening on port 3001`));

app.get('/',(req,res) => {
  const title="2FA SDK"
  const body = renderToString(<App/>)
  res.send(
    Html({
      body,
      title,
    })
  )
})

Мой html.js (простой шаблон):

const Html = ({ body, styles, title }) => `
  <!DOCTYPE html>
  <html>
    <head>
      <title>${title}</title>
    </head>
    <body style="margin:0">
      <div id="app">${body}</div>
    </body>
  </html>
`;

Мой app.js (с использованием пользовательского интерфейса, минимум)

render(){
    return(
        <div className="container">
            <div>
                <TextField 
                    label="Application Name"
                    type="text" 
                    variant="outlined"
                    onChange={this.handleApplicationName}
                />
            </div>
            <div>
                <FormLabel>Phone</FormLabel>
                <div>
                    <OutlinedInput
                        value={this.state.textmaskArray[2]}
                        onChange={(e) => this.handlePhoneNumber(e,2)}
                        labelWidth={200}
                    />
                </div>
            </div>
            <Button variant="contained" color="primary" onClick={this.props.buttonAction}>
            </Button>
        </div>

Часть файла App.js, использующая реактив:

render(){
    return(
      <CardControl
        title={"Code Authention"}
        message={"For your security, we need to verify your identity by sending a code to your phone number"}
        >
        <Container>
            <Row>
                <Col>
                    <div>{this.props.phoneList}</div>
                </Col>
                <Col>
                    <div>{this.props.methodList}</div>
                </Col>
            </Row>
            <Button className="sm-2" disabled={this.props.disabled} color="info" onClick={this.props.buttonAction}>{this.props.buttonName}</Button>
        </Container>
      </CardControl>

) } Мой webpack.config.js:

const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const HtmlWebPackPlugin = require("html-webpack-plugin");
const nodeExternals = require("webpack-node-externals");

module.exports = [
    {
        /*Config for backend code*/ 
        entry: './src/server/server.js',
        target: 'node',
        output: {
            filename: 'server.js'
        },
        externals: [nodeExternals()],
        module: {
            rules: [
                {
                    test: /\.(js|jsx)$/,
                    exclude: /node_modules/,
                    use: {
                        loader: "babel-loader"
                    }
                },
                {
                    test: /\.html$/,
                    use: {
                        loader: "html-loader",
                        options: { minimize: true }
                    }
                },
                {
                    test: /\.css$/,
                    use: [MiniCssExtractPlugin.loader,"css-loader"]
                }
            ]
        },
        plugins: [
            new HtmlWebPackPlugin({
                template: "./public/index.html",
                filename:"./index.html"
            }),
            new MiniCssExtractPlugin({
                filename: "[name].css",
                chunkFilename:"[id].css"
            })
        ]
    },
]

Что я использую : Create-react-app

Что я пробовал : Я установил загрузчики CSS, но он не работает вообще. Я также посмотрел документ material-ui о рендеринге на стороне сервера, и мне кажется, что я просто упускаю небольшую часть, и инструкции, которые они предоставили, могут быть излишними.

Что мне нужно помочь с : я пытаюсь выяснить, почему компонент пользовательского интерфейса из material-ui или bootstrap вообще не рендерится. Я подозреваю, что nodeExternal исключает их, но я не уверен.

1 Ответ

0 голосов
/ 16 января 2019

Вам нужно будет гидрировать визуализированный HTML-код на стороне клиента, чтобы реакция вступила во владение.

Создайте файл client.js с:

import React from 'react';
import ReactDOM from 'react-dom';
ReactDOM.hydrate(
  <App/>,
  document.querySelector('#app'),
);

обратите внимание, что гидрат должен соответствовать тому, что renderToString отрисовал.

Затем добавьте это как дополнительную запись в конфигурацию вашего веб-пакета:

module.exports = [
{
        /*Config for backend code*/ 
        entry: './src/server/server.js',
        target: 'node',
        output: {
            filename: 'server.js'
        },
        externals: [nodeExternals()],
        module: {
            rules: [
                {
                    test: /\.(js|jsx)$/,
                    exclude: /node_modules/,
                    use: {
                        loader: "babel-loader"
                    }
                },
                {
                    test: /\.html$/,
                    use: {
                        loader: "html-loader",
                        options: { minimize: true }
                    }
                },
                {
                    test: /\.css$/,
                    use: [MiniCssExtractPlugin.loader,"css-loader"]
                }
            ]
        },
        plugins: [
            new HtmlWebPackPlugin({
                template: "./public/index.html",
                filename:"./index.html"
            }),


  new MiniCssExtractPlugin({
            filename: "[name].css",
            chunkFilename:"[id].css"
        })
    ]
},
{ 
   entry: './client.js',
   output: {
      filename: 'bundle.js',
   },
   module: {
      rules: [ {
          test: /\.js$/,
          exclude: /node_modules/,
          loader: 'babel-loader',
      },
   ],
 },
]

Измените код рендеринга html, включив его:

const Html = ({ body, styles, title }) => `
  <!DOCTYPE html>
  <html>
    <head>
      <title>${title}</title>
    </head>
    <body style="margin:0">
      <div id="app">${body}</div>
      <script async src="/bundle.js"></script>
    </body>
  </html>
`;

Я не уверен на 100% в том, будет ли работать этот точный код, но это общая идея.

...