【问题标题】:Code splitting and server-side rendering (React is not defined)代码拆分和服务端渲染(React 未定义)
【发布时间】:2016-05-03 22:30:07
【问题描述】:

我正在构建一个具有代码拆分功能的同构/通用 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 编译整个应用程序时,没有任何问题。

【问题讨论】:

    标签: reactjs webpack react-router babeljs koa


    【解决方案1】:

    您还必须在 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)
      )
    ));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-02-26
      • 2017-06-04
      • 2020-11-16
      • 1970-01-01
      • 2018-04-26
      • 2017-01-15
      • 2016-07-16
      • 1970-01-01
      相关资源
      最近更新 更多