带有 Nashorn 和 Tomcat 的通用 Reactjs

Universal Reactjs with Nashorn and Tomcat

对于我当前的项目,我正在尝试创建一个通用的 reactjs 网站。我当前的服务器架构限制我只能使用 Tomcat 应用程序服务器。安装 nodejs 服务器不是一个选项。

作为 POC,我使用了一个示例存储库 (https://github.com/pgrimard/spring-boot-react),其中包含与在服务器上呈现的 react-router 的反应。虽然 运行 这个例子我得到以下错误:

org.springframework.scripting.support.StandardScriptEvalException: TypeError: 0 ,> u.createServerRenderContext is not a function in <eval> at line number 1

此错误发生在 server.js 文件中,同时设置 react-router 上下文。有没有人有在 Tomcat 容器中使用 SSR 的更大反应应用程序的经验?或者还有其他解决方案吗?

提前致谢!

我运行遇到了同样的问题。

我是节点的新手,但是如果你检查 node_modules 文件夹,以及 react-router v4 documentation,没有提到 ServerRouter class,就像在client.js文件中调用的那样。

可能创建 createServerRenderContext 函数也不存在。至少不在这个模块中。

尝试用 StaticRouter 替换它。

编辑:

设法通过安装最新版本的 ReactRouter 4 beta 使其工作

npm install --save react-router-dom@next
npm install --save react-router@next

然后更改server.js文件:

import React from 'react';
import ReactDOMServer from 'react-dom/server';
import {StaticRouter} from 'react-router';
import {createStore, applyMiddleware} from 'redux';
import thunkMiddleware from 'redux-thunk';
import {Provider} from 'react-redux';
import serialize from 'serialize-javascript';
import reducer from './reducers';
import App from 'components/App';

window.render = (template, model) => {
      const context = {};
      const req = JSON.parse(model.get('req'));
      const initialState = JSON.parse(model.get('initialState'));

      const store = createStore(reducer, initialState, applyMiddleware(thunkMiddleware));

      const markup = ReactDOMServer.renderToString(
        <Provider store={store}>
          <StaticRouter location={req.location} context={context}>
            <App/>
          </StaticRouter>
        </Provider>
      );

      return template
        .replace('SERVER_RENDERED_HTML', markup)
        .replace('SERVER_RENDERED_STATE', serialize(initialState, {isJSON:true}));
};

client.js 与 :

import React from 'react';
import ReactDOM from 'react-dom';
import {BrowserRouter} from 'react-router-dom';
import {createStore, applyMiddleware} from 'redux';
import thunkMiddleware from 'redux-thunk';
import {Provider} from 'react-redux';
import reducer from './reducers';
import App from 'components/App';

const store = createStore(reducer, window.__PRELOADED_STATE__, applyMiddleware(thunkMiddleware));

const markup = (
  <Provider store={store}>
    <BrowserRouter>
      <App/>
    </BrowserRouter>
  </Provider>
);

ReactDOM.render(markup, document.getElementById('app'));

最后 App.js

import React from 'react';
import {Route, Link} from 'react-router-dom';
import Home from 'components/Home';
import Child from 'components/Child';
import 'styles/main.css';

export default function App() {
  return (
    <div>
      <h1>Hello Server Side Rendering!!</h1>

      <ul>
        <li><Link to="/">{'Home'}</Link></li>
        <li><Link to="/child">{'Child'}</Link></li>
      </ul>

      <Route exactly path="/" component={Home}/>
      <Route path="/child" component={Child}/>

    </div>
  );
}

我删除了 Miss 对象,因为它在这个版本的 react-router 中不存在

我发表了一篇关于使用nashorn做react SSR的文章。 https://medium.com/@jimmy_shen/use-nashorn-engine-to-do-server-side-rendering-with-react-eba835e33d77 or 使用Nashorn Engine进行React Server-Side Rendering

关键是 Nashorn 关于 XmlHttpRequest 和 WebAPI 的 polyfill。 nashorn-polyfill 会做到的。

您可以查看 Demo。该应用程序包含 React、Apollo、React-Router v4 堆栈。