使用 react-router 的服务器端渲染不起作用

Server-side rendering with react-router is not working

我正在使用 express,我想在服务器端做一些基本的路由。目前我只是想设置路由器来做任何事情。现在它总是 returns 一个 404.

我相信我已经按照 https://github.com/rackt/react-router/blob/master/docs/guides/advanced/ServerRendering.md 上列出的说明进行操作。

它是您所能得到的最基本的:一个快速服务器,用于路由每个请求以由上面列出的 link 中的代码处理,以及一个将所有内容路由到 AppTemplate 组件的 ReactRouter。

它肯定会到达 routes.js 中的回调,因为它 returns 'Not found' 每个请求。

我怀疑它是否重要,但我通过 iisnode 在 IIS 中 运行 它。我在调试时遇到了麻烦,这是我从 express-react-views 切换到通过 <Router>.

路由的原因之一

让我知道我还能为您提供哪些其他信息。

文件结构:

server/
-- server.js // just calls babel-register and express-app.js
-- express-app.js
-- router.js

server/views/
-- app-template.js
-- routes.js

server/express-app.js

import Express from 'express';
import BodyParser from 'body-parser';
import CookieParser from 'cookie-parser';

let app = new Express();
export default app;

app.enable('trust proxy');

app.use('/public', Express.static('../dist'));

app.use(BodyParser.urlencoded({ extended: true }));
app.use(BodyParser.json());
app.use(CookieParser());

// some rest API code here, currently commented out

app.set('tokenSecret', process.env.tokenSecret);

require('./router');

server/router.js

// copied right from https://github.com/rackt/react-router/blob/master/docs/guides/advanced/ServerRendering.md.
import { renderToString } from 'react-dom/server';
import { match, RouterContext} from 'react-router';

import app from './express-app';
import Routes from './views/routes';

app.get('/*', (req, res) => {
    match({ Routes, location: req.originalUrl }, (error, redirectLocation, renderProps) => {
        if (error) {
            res.status(500).send(error.message);
        } else if (redirectLocation) {
            res.redirect(302, redirectLocation.pathname + redirectLocation.search);
        } else if (renderProps) {
            res.status(200).send(renderToString(<RouterContext {...renderProps} />));
        } else {
            res.status(404).send('Not found');
        }
    });
});

server/views/routes.js

import React from 'react';
import {Router, Route, IndexRoute} from 'react-router';

import AppTemplate from './app-template';

export default (
    <Router>
        <Route path='/' component={AppTemplate}>
        </Route>
    </Router>
);

server/views/app-template.js

import React from 'react';

export default class AppTemplate extends React.Component {
    constructor() {
        super();
    }

    render() {
        return (
            <html>
                <head>
                </head>
                <body>
                    <div id='app' />
                </body>
            </html>
        );
    }
};

几周前我遇到了这个问题,但不知何故让它工作了,这里有一些我做的不同的事情可能会或可能不会影响你的实施:

  1. 我没有使用 express.get,而是使用了没有指定路径的 express.use,这意味着 react-router 更像是中间件而不是请求处理程序。

  2. 在要匹配的第一个参数中,我的对象键是 "routes" 而不是 "Routes"

  3. 我也在使用 'history' 模块,所以我的位置是使用 createLocation(req.originalUrl) 创建的 - createLocation 来自 'history'.

试试这个东西,否则我也可以 post 我的代码的改编版本。

OP 备注:

这是#2。 babel 语法 { Routes, location: req.url } 将对象扩展为具有 Routes 的键,而 match() 期望键为 routes。这可以通过

来解决
import routes from './views/routes';
...
{ routes, location: req.url }

按照建议,或

import Routes from './views/routes';
...
{ routes: Routes, location: req.url }