【问题标题】:react + redux + saga + server side rendering + how to stop additional ajax calls for server side rendered page?react + redux + saga + 服务器端渲染 + 如何停止对服务器端渲染页面的额外 ajax 调用?
【发布时间】:2018-04-08 09:04:36
【问题描述】:

我正在做一个网络项目。 在这个项目中,我们使用带有节点、表达和反应的服务器端渲染。 对于获取数据和 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}`);
    }
});

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

【问题讨论】:

    标签: ajax reactjs redux server-side-rendering isomorphic-javascript


    【解决方案1】:

    这都是关于存储数据的。 我们应该以某种方式将存储数据发送到客户端,并将这些数据用于存储在客户端。

    对我来说最好的解决方案是通过 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);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-03-26
      • 1970-01-01
      • 2020-06-29
      • 2019-10-05
      • 1970-01-01
      • 2015-05-07
      • 1970-01-01
      相关资源
      最近更新 更多