首页 > 解决方案 > React服务器端渲染不输出索引页面

问题描述

我一直在用 React 玩服务器端渲染(SSR),我几乎可以让它工作,除了主页没有从服务器加载。

如果我使用替代路由,例如 /test 或 /404,它会从服务器加载。如果我转到 / index 路径,它只会加载我的反应应用程序,而不是来自服务器的 html。我通过禁用 javascript 对此进行了测试,并注意到它正在发生。

这是我正在使用的服务器代码:

import path from 'path';
import fs from 'fs';
import React from 'react';
import express from 'express';
import cors from 'cors';
import configureStore from '../src/redux/store/configureStore';
import { Provider } from 'react-redux';
import { StaticRouter } from 'react-router-dom';
import { renderToString } from 'react-dom/server';
import Client from '../src/client/index.jsx';

/* Express settings */
const app  = express();
const PORT = process.env.PORT || 3334;
app.disable('x-powered-by');
app.use(cors());
app.use(express.static('./dist'));
app.use(handleRender);

/* Handle React Application */
function handleRender(req, res) {
    const context   = {}; 
    const store     = configureStore({});
    const indexFile = path.resolve('./dist/index.html');
    const html      = renderToString(
        <Provider store={store}>
            <StaticRouter location={req.url} context={context}>
                <Client />
            </StaticRouter>
        </Provider>
    );
    fs.readFile(indexFile, 'utf8', (err, data) => {
        if (err) {
            console.error('Something went wrong:', err);
        }        
        res.status(context.status||200).send( 
            data.replace(
                '<div id="root"></div>',
                `
                <div id="root">${html}</div>
                <script>                
                    window.__PRELOADED_STATE__ = ${JSON.stringify(store)}
                </script>
                `
            )
        );
    });    
}

/* Listen for connections */
app.listen(PORT, () => {
    console.log(`  Server is running on port ${PORT}`);
});

这是我与路线的主要反应组件:

import React from 'react';
import { 
    Switch, 
    Route
} from 'react-router-dom';
import App from './components/App/index.jsx';
import NotFound from './NotFound.jsx';

const Test = () => (
    <h1>Test!</h1>
);

const Bruh = () => (
    <h1>Bruh!</h1>
);

const Client = () => (
    <Switch>
        <Route path="/" exact component={App} />
        <Route path="/test" exact component={Test} />
        <Route path="/bruh" exact component={Bruh} />
        <Route component={NotFound} />
    </Switch>
);

export default Client;

最后,这是我的 react 应用程序的 index.js 文件:

import React from 'react';
import { hydrate } from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import { Provider } from 'react-redux';
import configureStore from './redux/store/configureStore';
import Client from './client/index.jsx';
import './styles/index.css';

/* Redux */
const preloadedState = window.__PRELOADED_STATE__ = {}; //initial state
delete window.__PRELOADED_STATE__;
const store         = configureStore(preloadedState);
const unsubscribe   = store.subscribe( () => {
    console.log("Store: ", store.getState());
});

/* Render / Hydrate App */
hydrate(
    <Provider store={ store }>
        <BrowserRouter>
            <Client />
        </BrowserRouter>
    </Provider>,
    document.getElementById('root')
);

我认为这就是一切。如果您需要更多信息,请告诉我。任何建议和帮助将不胜感激。

谢谢!

标签: javascriptnode.jsreactjsreact-router-v4server-side-rendering

解决方案


推荐阅读