Рендеринг на стороне сервера с помощью Webpack Express и 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 => /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;

Мой конфиг вебпака

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

{
"presets": ["es2015", "react"]
}
  1. Я получаю ошибку с жадностью

500 Internal Server Error Ответ: element.type.toLowerCase не является
функция

  1. Ошибка, которую я получаю с nodeJS

Предупреждение: React.createElement: тип недействителен — ожидается строка
(для встроенных компонентов) или класс / функция (для составного
компоненты) но получил: объект. Вы, вероятно, забыли экспортировать свой
компонент из файла, в котором он определен, или вы могли перепутать
импорт по умолчанию и именованный.
в неизвестном

  1. Что я получаю, когда связываю свои файлы:

Выход Webpack

Я пробовал много разных вещей, но я не могу понять, почему это выдает ошибку.


Редактировать:

С этой конфигурацией я могу заставить вещи работать должным образом, проблема, кажется, прибывает из части импорта:

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 [email protected]
3 info using [email protected]
4 verbose run-script [ 'prestart', 'start', 'poststart' ]
5 info lifecycle [email protected]~prestart: [email protected]
6 info lifecycle [email protected]~start: [email protected]
7 verbose lifecycle [email protected]~start: unsafe-perm in lifecycle true
8 verbose lifecycle [email protected]~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 [email protected]~start: CWD: /home/dev/www
10 silly lifecycle [email protected]~start: Args: [ '-c', 'node server.js' ]
11 silly lifecycle [email protected]~start: Returned: code: 1  signal: null
12 info lifecycle [email protected]~start: Failed to exec start script
13 verbose stack Error: [email protected] 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 [email protected]
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 [email protected] start: `node server.js`
22 error Exit status 1
23 error Failed at the [email protected] start script.
23 error This is probably not a problem with npm. There is likely additional logging output above.
24 verbose exit [ 1, true ]

1

Решение

В твоем компоненте попробуй.

import * as React from 'react';

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

module.exports = App;

Может быть просто получить экспорт по умолчанию из пакета реакции.

0

Другие решения

По умолчанию Webpack не выводит экспорт CommonJS, как вы ожидаете.

Вы можете попробовать добавить

output: {
....
library: 'server',
libraryTarget: 'commonjs2'
}

target: 'node'

к модулю вывода в Webpack.
И на всякий случай, если вы хотите импортировать любой sass (или любые другие файлы в вашем App.js), убедитесь, что они ссылаются относительно их источника. Они будут объединены в созданный пакет. Так что не включайте свой App.sass в свои записи.

Надеюсь, это поможет.

0

По вопросам рекламы [email protected]