react + redux + saga + 服务器端渲染 + 如何停止对服务器端渲染页面的额外 ajax 调用?

react + redux + saga + server side rendering + how to stop additional ajax calls for server side rendered page?

我正在做一个网络项目。 在这个项目中,我们使用节点、表达和反应的服务器端渲染。 为了获取数据和 Redux,我们使用 Redux-Saga。 只有一个问题。 每个页面都是从服务器呈现的,当我们到达浏览器时,我们的应用程序就像客户端应用程序一样。 如果一个页面有一些 ajax 调用,并且该页面从服务器呈现,尽管它具有来自服务器所需的所有数据,但在客户端它会进行 ajax 调用。 我想停止额外的 ajax 调用。 我只想跳过 ajax 对服务器请求页面的调用。

这是客户端的 index.jsx 文件。

import App from './App'
import ReactDOM from 'react-dom'
import React from 'react';
import { Provider } from 'react-redux';
import { ConnectedRouter } from 'react-router-redux'
import getStore from './getStore';
import createHistory from 'history/createBrowserHistory';

import './styles/styles.scss';

const history = createHistory();
const store = getStore(history);

if (module.hot) {
    module.hot.accept('./App', () => {
        const NextApp = require('./App').default;
        render(NextApp);
    });
}

const render = (_App) => {
    ReactDOM.render(
    <Provider store={store}>
        <ConnectedRouter history={history}>
            <_App />
        </ConnectedRouter>
    </Provider>
    , document.getElementById("AppContainer"));
};

store.subscribe(() => {
const state = store.getState();
if (state.items.length > 0) {
    render(App);
}
});
const fetchDataForLocation = location => {
if (location.pathname === "/") {
    store.dispatch({ type: `REQUEST_FETCH_ITEMS` });
}
};
fetchDataForLocation(history.location);
 history.listen(fetchDataForLocation);

这是服务器

的index.js文件
import path from 'path';
import express from 'express';
import webpack from 'webpack';
import yields from 'express-yields';
import fs from 'fs-extra';
import App from '../src/App';
import { renderToString } from 'react-dom/server';
import React from 'react'
import { argv } from 'optimist';
import { ConnectedRouter } from 'react-router-redux';
import getStore from '../src/getStore'
import { Provider } from 'react-redux';
import createHistory from 'history/createMemoryHistory';
import open from 'open';
import { get } from 'request-promise';

const port = process.env.PORT || 4000;
const app = express();

const useServerRender = argv.useServerRender === 'true';
const inDebugMode = argv.inDebugMode == 'true';

let indexPath = inDebugMode ? '../public/index.html' : './public/index.html';
let mediaPath = inDebugMode ? '../src/styles/media' : './src/styles/media';

app.use('/media', express.static(mediaPath));

function* getItems() {
    let data = yield get("http://localhost:3826/api/item/getall", { gzip: true });
    return JSON.parse(data);
}

if (process.env.NODE_ENV === 'development') {
    const config = require('../webpack.config.dev.babel.js').default;
    const compiler = webpack(config);

    app.use(require('webpack-dev-middleware')(compiler, {
        noInfo: true,
        stats: {
            assets: false,
            colors: true,
            version: false,
            hash: false,
            timings: false,
            chunks: false,
            chunkModules: false
        }
    }));
    app.use(require('webpack-hot-middleware')(compiler));
} else {
    app.use(express.static(path.resolve(__dirname, '../dist')));
}

app.get(['/', '/aboutus'], function* (req, res) {
    let index = yield fs.readFile(indexPath, "utf-8");

    const initialState = {
        items: []
    };

    if (req.path == '/') {
        const items = yield getItems();
        initialState.items = items.data.items;
    }

    const history = createHistory({
        initialEntries: [req.path]
    });

    const store = getStore(history, initialState);

    if (useServerRender) {
        const appRendered = renderToString(
            <Provider store={store}>
                <ConnectedRouter history={history}>
                    <App />
                </ConnectedRouter>
            </Provider>
        );
        index = index.replace(`<%= preloadedApplication %>`, appRendered)
    } else {
        index = index.replace(`<%= preloadedApplication %>`, `Please wait while we load the application.`);
    }
    res.send(index);
});

app.listen(port, '0.0.0.0', () => {
    console.info(`Listening at http://localhost:${port}`);
    if (process.env.NODE_ENV === 'development') {
        open(`http://localhost:${port}`);
    }
});

我认为如果我们能够以某种方式在客户端使用服务器端存储,我们可能会克服这个问题。

一切都与商店数据有关。 我们应该以某种方式将存储数据发送到客户端,并在客户端使用这些数据进行存储。

对我来说,最好的解决方案是通过 html:

<script id='app-props' type='application/json'>
        <![CDATA[<%= initialData %>]]>
    </script>

在存储文件中,我是这样检索的:

 if (typeof window !== 'undefined') {
    let initialDataEl = document.getElementById('app-props');
    try {
        let props = initialDataEl.textContent;
        props = props.replace("<![CDATA[", "").replace("]]>", "");
        defaultState = JSON.parse(props);
    }
    catch (err) {
        console.log(err);
    }
}