I am a beginner with React-Router and only about a year into Web development, for that matter. Because my routes return 404s when I directly access them versus using a Link
or Redirect
component, I am trying to implement server-side rendering.
I have looked through the documentation here: https://reacttraining.com/react-router/web/guides/server-rendering
and do not quite grok how it is that they're using ES6 syntax. My server.js
file is in the root of my project and I don't think Node understands import
or JSX markup.
I tried running my desired ES6 code through the online Babel transpiler and ended up in OK shape. Right now, my Express server looks like this in server.js:
// server.js
require('babel-register')({
presets: ['es2015', 'react', 'stage-0']
})
var express = require('express')
var webpack = require('webpack')
var webpackDevMiddleware = require('webpack-dev-middleware')
var webpackHotMiddleware = require('webpack-hot-middleware')
var config = require('./webpack.config.js')
var compiler = webpack(config)
var react = require('react')
var react2 = _interopRequireDefault(react)
var server = require('react-dom/server')
var server2 = _interopRequireDefault(server)
var reactRouter = require('react-router')
var App = require('./app/components/App.jsx').default
var App2 = _interopRequireDefault(App)
function _interopRequireDefault (obj) { return obj && obj.__esModule ? obj : { default: obj } }
var app = express()
const PORT = process.env.PORT || 3003
app.use(function (req, res, next) {
if (req.headers['x-forwarded-proto'] === 'https') {
res.redirect('http://' + req.hostname + req.url)
} else {
next()
}
})
app.use(webpackDevMiddleware(compiler, {
publicPath: config.output.publicPath,
stats: {
colors: true
},
historyApiFallback: true
}))
app.use(webpackHotMiddleware(compiler, {
log: console.log,
path: '/__webpack_hmr',
heartbeat: 10 * 1000
}))
app.use(express.static('public'))
app.use(function (req, res) {
var context = {}
var html = server2.default.renderToString(react2.default.createElement(
reactRouter.StaticRouter,
{
location: req.url,
context: context
},
react2.default.createElement(App2.default, null)
))
if (context.url) {
res.writeHead(301, {
Location: context.url
})
res.end()
} else {
res.write('\n <!doctype html>\n <div id="app">' + html + '</div>\n ')
res.end()
}
})
app.get('*', function (req, res) {
res.sendFile(__dirname + '/index.html')
})
app.listen(PORT, function () {
console.log('Express server is up on port ' + PORT)
})
The server comes up without an error and client-side routing is working correctly, but if I try to hit a route directly now, I get this error:
Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined.
What am I not seeing here/doing incorrectly to render correctly on the server-side? Apologies in advance that the ES5 transpilation of the JSX/import statements is sort of a pain readability-wise.
via N.L.
No comments:
Post a Comment