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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了react + redux + saga +服务器端渲染+如何停止服务器端渲染页面的额外ajax调用?相关的知识,希望对你有一定的参考价值。

我正在开展一个网络项目。在这个项目中,我们使用服务器端渲染与节点,表达和反应。为了获取数据和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);
    }
}

以上是关于react + redux + saga +服务器端渲染+如何停止服务器端渲染页面的额外ajax调用?的主要内容,如果未能解决你的问题,请参考以下文章

前端生态系统总结

React dva 的使用

rematch:当你受不了redux繁琐写法的时候,是时候了解一波rematch了

react+redux教程redux服务端渲染流程

如何在 React/redux 中进行服务器端渲染?

react服务端渲染redux添加