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