我正在构建一个带有代码分割的同构/通用React应用程序。即使我设法通过webpack编译客户端包没有问题,服务器也无法呈现页面,在执行函数renderToString
时抛出错误。
运行服务器时,堆栈跟踪如下:
ReferenceError: React is not defined
at /xx/src/server/server.js:84:16
at /xx/node_modules/react-router/lib/match.js:65:5
at /xx/node_modules/react-router/lib/createTransitionManager.js:118:11
at done (/xx/node_modules/react-router/lib/AsyncUtils.js:79:19)
at /xx/node_modules/react-router/lib/AsyncUtils.js:85:7
at /xx/src/routes/About/index.js:12:7
at Function.require.ensure (/xx/src/routes/About/index.js:5:10)
at Object.getComponent (/xx/src/routes/About/index.js:11:13)
at getComponentsForRoute (/xx/node_modules/react-router/lib/getComponents.js:62:16)
at /xx/node_modules/react-router/lib/getComponents.js:74:5
---------------------------------------------
at Application.callback (/xx/node_modules/koa/lib/application.js:129:47)
at Application.listen (/xx/node_modules/koa/lib/application.js:64:43)
at Object.<anonymous> (/xx/src/server/server.js:103:8)
at Module._compile (module.js:413:34)
at loader (/xx/node_modules/babel-register/lib/node.js:158:5)
at Object.require.extensions.(anonymous function) [as .js] (/xx/node_modules/babel-register/lib/node.js:168:7)
at Module.load (module.js:357:32)
at Function.Module._load (module.js:314:12)
at Module.require (module.js:367:17)
服务器文件server.js
包含:
import Koa from 'koa'
import convert from 'koa-convert'
import webpack from 'webpack'
import webpackMiddleware from 'webpack-dev-middleware'
import config from '../../webpack.config'
import ReactDOM from 'react-dom/server';
import { Provider } from 'react-redux'
import { createMemoryHistory, RouterContext, match } from 'react-router';
import { IntlProvider } from 'react-intl'
import { trigger } from 'redial'
import localeMessages from '../locales/en'
import configureStore from '../store/configureStore'
function createPage(html, scriptTag) {
return `
<!doctype html>
<html>
<body>
${html}
${scriptTag}
</body>
</html>
`
}
const is_developing = process.env.NODE_ENV == 'development'
const port = process.env.PORT || 5000
const server = new Koa()
server.use((req, res) => {
const store = configureStore()
const history = createMemoryHistory(req.path)
const routes = require('../routes')
const { dispatch, getState } = store
match({ routes, history }, (error, redirectLocation, renderProps) => {
// Get array of route handler components:
const { components } = renderProps;
// Define locals to be provided to all lifecycle hooks:
const locals = {
path: renderProps.location.pathname,
query: renderProps.location.query,
params: renderProps.params,
// Allow lifecycle hooks to dispatch Redux actions:
dispatch
};
const content = ReactDOM.renderToString(
<Provider store={store}>
<IntlProvider locale="en"
feedbacks={localeMessages}>
<RouterContext {...renderProps} />
</IntlProvider>
</Provider>
);
// Wait for async data fetching to complete, then render:
trigger('fetch', components, locals)
.then(() => {
const state = getState();
const content = ReactDOM.renderToString(
<Provider store={store}>
<IntlProvider locale="en"
feedbacks={localeMessages}>
<RouterContext {...renderProps} />
</IntlProvider>
</Provider>
);
const html = createPage(content, scriptTag)
resolve({ html, state })
})
.catch(e => console.log(e))
})
})
server.listen(port, '0.0.0.0', () => {
console.info(`Listening on port ${port} (0.0.0.0)`)
})
server.on('error', (err, ctx) => {
console.log('error', err, ctx)
})
module.exports = server
整个例程似乎正常工作:从getState()
派生的状态看起来很好,并且不同的路由符合预期(无论我在浏览器上键入的内容与循环中的正确路由相关联)。
我正在关注react-router异步路由(如本example中所述)。在此特定问题中,routes/About/index.js
的内容为:
// Polyfill (require for server side)
if (typeof require.ensure !== 'function') require.ensure = (d, c) => c(require)
module.exports = {
path: 'about',
getComponent(nextState, cb) {
require.ensure([], (require) => {
cb(null, require('./components/About').default)
})
}
}
我还仔细检查了不同的组件,确保它们都导入了React库(即import React from 'react'
)。再次,当我运行webpack来编译整个应用程序时,没有问题。
答案 0 :(得分:2)
您还必须在server.js
文件上导入React,因为在转换了以下内容后
const content = ReactDOM.renderToString(
<Provider store={store}>
<IntlProvider locale="en"
feedbacks={localeMessages}>
<RouterContext {...renderProps} />
</IntlProvider>
</Provider>
);
看起来像这样
var content = ReactDOM.renderToString(React.createElement(
Provider,
{ store: store },
React.createElement(
IntlProvider,
{ locale: "en",
feedbacks: localeMessages },
React.createElement(RouterContext, renderProps)
)
));