使用Webpack Express和React进行服务器端渲染

时间:2018-02-12 21:42:35

标签: php node.js reactjs webpack serverside-rendering

我正在尝试学习React,经过多次尝试运行我的React服务器端渲染配置后,我已将代码缩减为最简单的示例,但我仍然无法理解为什么它不起作用。

案例

我的控制器:

$router = $container->get(Router::class);
$router->get('/test/{name:.*}', function ($request) use ($container) {
    /** @var $request \GuzzleHttp\Psr7\ServerRequest **/
    $client = new Client(['base_uri' => 'http://localhost:3000']);
    $response = $client->post('/', [
        'query' => ['module' => 'App'],
    ]);
    $contents = $response->getBody()->getContents();

    return $contents;
});

我正在使用GuzzleHttp库

我的服务器配置:

/path/to/project/resources/server.js => /path/to/project/server.js

import express from 'express'
import React from 'react'
import ReactDOMServer from 'react-dom/server'

let app = express()

app.use('/', (request, response) => {
  try {
    let App = require('../public/dist/js/' + request.query.module)
    response.send(
      ReactDOMServer.renderToString(<App/>)
    )
  } catch (error) {
    response.status(500).send(error.message)
  }
})

app.listen(3000)

我的组件

/path/to/project/resources/assets/js/App.jsx =&gt; /path/to/project/public/dist/js/App.js

import React from 'react';

class App extends React.Component {
  render () {
    return <h1>Hello World!</h1>;
  }
}

module.exports = App;

我的webpack配置

const path = require('path');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const UglifyJsPlugin = require ('uglifyjs-webpack-plugin');

function assets(path) {
  return './resources/assets/' + path;
}

const config = {
  entry: [
    assets('js/App.jsx'),
    assets('sass/app.scss')
  ],
  output: {
    path: path.resolve(__dirname, 'public/dist'),
    filename: 'js/App.js',
    publicPath: '/dist/'
  },
  resolve: {
    extensions: ['.js', '.jsx']
  },
  module: {
    rules: [
      { // es2015
        test: /\.(js|jsx)/,
        use: ['babel-loader'],
        exclude: [/node_modules/]
      },
      { // css / sass / scss loaders
        test: /\.(css|sass|scss)$/,
        use: ExtractTextPlugin.extract({
          use: ['css-loader', 'sass-loader'],
        })
      }
    ]
  },
  plugins: [
    new ExtractTextPlugin({
      filename: 'css/[name].bundle.css',
      allChunks: true
    }),
    new UglifyJsPlugin()
  ]
};

const server = {
  entry: [
    './resources/server.js'
  ],
  output: {
    path: path.resolve(__dirname, '.'),
    filename: 'server.js',
    publicPath: '/dist/'
  },
  resolve: {
    extensions: ['.js', '.jsx']
  },
  module: {
    rules: [
      { // es2015
        test: /\.(js|jsx)/,
        use: ['babel-loader'],
        exclude: [/node_modules/]
      }
    ]
  },
  plugins: [
    //new UglifyJsPlugin()
  ],
  target: 'node'
};

module.exports = [config, server];

Babelrc config

{
  "presets": ["es2015", "react"]
}

结果

  1. 我得到Guzzle的错误
  2.   

    500 Internal Server Error响应:element.type.toLowerCase不是   功能

    1. 我遇到nodeJS错误
    2.   

      警告:React.createElement:type无效 - 需要一个字符串   (对于内置组件)或类/函数(对于复合   组件)但得到:对象。你可能忘了导出你的   来自其定义的文件中的组件,或者您可能已经混淆了   默认和命名导入。       在未知

      1. 捆绑文件时收到的内容:
      2. Webpack output

        我尝试了很多不同的东西,但我无法理解为什么这会引发错误。

        编辑:

        通过这种配置,我能够正常工作,问题似乎来自导入部分:

        import express from 'express'
        import * as React from 'react'
        import ReactDOMServer from 'react-dom/server'
        
        let app = express()
        
        class App extends React.Component {
          render () {
            return <h1>Hello World!</h1>;
          }
        }
        
        const component = <App />;
        
        app.use('/', (request, response) => {
          try {
            response.send(
              ReactDOMServer.renderToString(component)
            )
          } catch (error) {
            response.status(500).send(error.message)
          }
        })
        
        app.listen(3000)
        

        编辑2:

        这是我从.npm

        中检索的日志
        0 info it worked if it ends with ok
        1 verbose cli [ '/usr/bin/node', '/usr/bin/npm', 'start' ]
        2 info using npm@5.6.0
        3 info using node@v8.9.4
        4 verbose run-script [ 'prestart', 'start', 'poststart' ]
        5 info lifecycle Framework@1.0.0~prestart: Framework@1.0.0
        6 info lifecycle Framework@1.0.0~start: Framework@1.0.0
        7 verbose lifecycle Framework@1.0.0~start: unsafe-perm in lifecycle true
        8 verbose lifecycle Framework@1.0.0~start: PATH: /usr/lib/node_modules/npm/node_modules/npm-lifecycle/node-gyp-bin:/home/dev/www/node_modules/.bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
        9 verbose lifecycle Framework@1.0.0~start: CWD: /home/dev/www
        10 silly lifecycle Framework@1.0.0~start: Args: [ '-c', 'node server.js' ]
        11 silly lifecycle Framework@1.0.0~start: Returned: code: 1  signal: null
        12 info lifecycle Framework@1.0.0~start: Failed to exec start script
        13 verbose stack Error: Framework@1.0.0 start: `node server.js`
        13 verbose stack Exit status 1
        13 verbose stack     at EventEmitter.<anonymous> (/usr/lib/node_modules/npm/node_modules/npm-lifecycle/index.js:285:16)
        13 verbose stack     at emitTwo (events.js:126:13)
        13 verbose stack     at EventEmitter.emit (events.js:214:7)
        13 verbose stack     at ChildProcess.<anonymous> (/usr/lib/node_modules/npm/node_modules/npm-lifecycle/lib/spawn.js:55:14)
        13 verbose stack     at emitTwo (events.js:126:13)
        13 verbose stack     at ChildProcess.emit (events.js:214:7)
        13 verbose stack     at maybeClose (internal/child_process.js:925:16)
        13 verbose stack     at Process.ChildProcess._handle.onexit (internal/child_process.js:209:5)
        14 verbose pkgid Framework@1.0.0
        15 verbose cwd /home/dev/www
        16 verbose Linux 4.9.0-4-amd64
        17 verbose argv "/usr/bin/node" "/usr/bin/npm" "start"
        18 verbose node v8.9.4
        19 verbose npm  v5.6.0
        20 error code ELIFECYCLE
        21 error errno 1
        22 error Framework@1.0.0 start: `node server.js`
        22 error Exit status 1
        23 error Failed at the Framework@1.0.0 start script.
        23 error This is probably not a problem with npm. There is likely additional logging output above.
        24 verbose exit [ 1, true ]
        

2 个答案:

答案 0 :(得分:0)

在您的组件中尝试。

import * as React from 'react';

class App extends React.Component {
  render () {
    return <h1>Hello World!</h1>;
  }
}

module.exports = App;

可能只是从反应包中获取默认导出。

答案 1 :(得分:0)

默认情况下,Webpack不会像您期望的那样输出CommonJS导出。

您可以尝试添加

<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
  <metadata>
    <id>BancaDigitalViewProvider</id>
    <version>1.0.37</version>
    <authors>Ibercaja</authors>
    <owners>Ibercaja</owners>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>Login View Provider</description>
    <copyright>Copyright 2018</copyright>
    <tags>Banca Digital View Provider</tags>
    <dependencies />
    <contentFiles>
      <files include="any/any/wwwroot/css/bd.css" buildAction="Content" copyToOutput="false" flatten="true" />
      <files include="any/any/wwwroot/js/bd.js" buildAction="Content" copyToOutput="false" flatten="true" />
    </contentFiles>
  </metadata>

  <files>
    <file src="contentFiles/any/any/wwwroot/css/bd.css" target="contentFiles/any/any/wwwroot/css/bd.css" />
    <file src="contentFiles/any/any/wwwroot/js/bd.js" target="contentFiles/any/any/wwwroot/js/bd.js" />
    <file src="bin\debug\BancaDigitalViewProvider.dll" target="lib\net47\BancaDigitalViewProvider.dll" />
  </files>
</package>

到Webpack中的输出模块。 如果你想导入任何sass(或你的App.js中的任何其他文件),请确保它们相对于它们的来源被引用。它们将捆绑在创建的包中。因此,请不要在您的参赛作品中包含您的App.sass。

希望有所帮助。

相关问题