Ich habe eine Anwendung mit Webpack als Modul Bundler und Babel als meine js Compiler konfiguriert. alles auf einer Knoten-Engine. Ich stellte fest, dass, wenn ich renne npm run dev
der folgende Ablauf wird:ReactDOM.renderToString sessionStorage ist nicht definiert, Fenster ist nicht definiert
Die webpack-dev-server.js
wird ausgeführt. die Datei ist die folgende:
const Express = require('express');
const webpack = require('webpack');
const webpackConfig = require('./dev.config');
const compiler = webpack(webpackConfig);
const host = 'localhost';
const port = 8080;
const serverOptions = {
contentBase: `http://${host}:${port}`,
quiet: true,
noInfo: true,
hot: true,
inline: true,
lazy: false,
publicPath: webpackConfig.output.publicPath,
headers: { 'Access-Control-Allow-Origin': '*' },
stats: { colors: true },
};
const app = new Express();
app.use(require('webpack-dev-middleware')(compiler, serverOptions));
app.use(require('webpack-hot-middleware')(compiler));
app.listen(port, function onAppListening(err) {
if (err) {
console.error(err);
} else {
console.info('==> Webpack development server listening on port %s', port);
}
});
Dann wird der server.js
require('./../server.babel');
const path = require('path');
const WebpackIsomorphicTools = require('webpack-isomorphic-tools');
const rootDir = path.resolve(require('../server/config').rootDir);
global.__CLIENT__ = false;
global.__SERVER__ = true;
global.__DEVELOPMENT__ = process.env.NODE_ENV !== 'production';
if (__DEVELOPMENT__) {
if (!require('piping')({
hook: true,
ignore: /(\/\.|~$|\.json|\.scss$)/i
})) {
return;
}
}
global.webpackIsomorphicTools = new WebpackIsomorphicTools(require('../webpack/webpack-isomorphic-tools'))
.development(__DEVELOPMENT__)
.server(rootDir,() => {
require('../server/server');
});
Express- und React Rendering:
import 'babel-polyfill';
// Server
import express from 'express';
import session from 'express-session';
import cookieParser from 'cookie-parser';
// React
import React from 'react';
import ReactDOM from 'react-dom/server';
import createHistory from 'react-router/lib/createMemoryHistory';
import { match } from 'react-router';
// Redux
import { Provider } from 'react-redux';
import { ReduxAsyncConnect, loadOnServer } from 'redux-connect';
import { syncHistoryWithStore } from 'react-router-redux';
import path from 'path';
import csurf from 'csurf';
import bodyParser from 'body-parser';
// Relative imports
import Html from '../shared/html';
import proxy from './proxy';
import createStore from '../shared/redux/create';
import { staticPath } from './config';
import { getRoutes } from '../shared/routes';
require('dotenv').config({
path: path.resolve(__dirname, '../.env'),
});
const SERVER_PORT = process.env.SERVER_PORT;
const APP_SECRET = process.env.APP_SECRET;
const API_PORT = process.env.API_PORT;
const API_HOST = process.env.API_HOST;
function renderPage({ renderProps, store, res, client, csrfToken }) {
loadOnServer({ ...renderProps, store, helpers: { client } })
.then(() => {
const component = (
<Provider store={store} key="provider">
<ReduxAsyncConnect {...renderProps} />
</Provider>
);
res.status(200);
res.send('<!doctype html>\n' +
ReactDOM.renderToString(
<Html
assets={webpackIsomorphicTools.assets()}
component={component}
csrfToken={csrfToken}
store={store}
/>,
),
);
})
.catch((err) => {
console.error(err.stack);
});
}
const app = express();
const csrf = csurf();
// express middlewares
// app.use(favicon(path.resolve(__dirname, '../static/favicon.ico'))); @TODO favicon @ilanus
app.use(bodyParser.json());
app.use(express.static(staticPath));
app.use(cookieParser(APP_SECRET));
app.use(session({
secret: APP_SECRET,
saveUninitialized: true,
resave: true,
}));
app.use(csrf);
app.use('/api', (req, res) => {
if (!req.xhr) res.redirect('/');
proxy.web(req, res, { target: `http://${API_HOST}:${API_PORT}` });
});
app.use((req, res) => {
const csrfToken = req.csrfToken();
if (__DEVELOPMENT__) {
// Do not cache webpack stats: the script file would change since
// hot module replacement is enabled in the development env
webpackIsomorphicTools.refresh();
}
const memoryHistory = createHistory(req.originalUrl);
const store = createStore({}, memoryHistory);
const history = syncHistoryWithStore(memoryHistory, store);
match({ history, routes: getRoutes(store), location: req.originalUrl },
(error, redirectLocation, renderProps) => {
if (redirectLocation) {
res.redirect(redirectLocation.pathname + redirectLocation.search);
} else if (error) {
console.error('ROUTER ERROR:', error);
res.status(500);
} else if (renderProps) {
renderPage({ renderProps, store, res, csrfToken });
} else {
res.status(404).send('Not found');
}
});
});
app.use((err, req, res) => {
if (err === 'EBADCSRFTOKEN') {
res.status(403);
res.send('invalid csrf token');
} else {
res.status(500);
res.send('Oops, internal server error');
}
});
app.listen(SERVER_PORT, (error) => {
if (error) {
console.error(error);
} else {
console.info(`App started listening on port ${SERVER_PORT}`);
}
});
Nun, wenn ich console.log('window', window, 'sessionStorage', sessionStorage);
innerhalb einer render()
Funktion oder componentDidMount()
eines versuchen zu reagieren Komponente Ich habe am Ende: sessionStorage is not defined, window is not defined
Fehler. Ich schätze, das liegt daran, dass ich den Stack auf der Serverseite laufen lasse und die dort nicht verfügbar sind. Was fehlt mir?