标签:
react+redux教程(一)connect、applyMiddleware、thunk、webpackHotMiddleware
react+redux教程(二)redux的单一状态树完全替代了react的状态机?
react+redux教程(三)reduce()、filter()、map()、some()、every()、...展开属性
react+redux教程(四)undo、devtools、router
react+redux教程(五)异步、单一state树结构、componentWillReceiveProps
连载中……
今天,我们要讲解的是react+redux服务端渲染。个人认为,react击败angular的真正“杀手锏”就是服务端渲染。我们为什么要实现服务端渲染,主要是为了SEO。
例子仍然是官方的计数器例子,不过我们实现了服务端渲染和state预加载。
源代码:
https://github.com/lewis617/myReact/tree/master/redux-examples/universal
首先,我们要模拟一个api,用于异步请求数据。代码如下:
common/api/counter.js
function getRandomInt(min, max) { return Math.floor(Math.random() * (max - min)) + min } export function fetchCounter(callback) { // Rather than immediately returning, we delay our code with a timeout to simulate asynchronous behavior setTimeout(() => { callback(getRandomInt(1, 100)) }, 500) // In the case of a real world API call, you‘ll normally run into a Promise like this: // API.getUser().then(user => callback(user)) }
server/server.js(部分代码)
// This is fired every time the server side receives a request app.use(handleRender) function handleRender(req, res) { // Query our mock API asynchronously fetchCounter(apiResult => { // Read the counter from the request, if provided const params = qs.parse(req.query) const counter = parseInt(params.counter, 10) || apiResult || 0 // Compile an initial state const initialState = { counter } // Create a new Redux store instance const store = configureStore(initialState) // Render the component to a string const html = renderToString( <Provider store={store}> <App /> </Provider> ) // Grab the initial state from our Redux store const finalState = store.getState() // Send the rendered page back to the client res.send(renderFullPage(html, finalState)) }) } function renderFullPage(html, initialState) { return ` <!doctype html> <html> <head> <title>Redux Universal Example</title> </head> <body> <div id="app">${html}</div> <script> window.__INITIAL_STATE__ = ${JSON.stringify(initialState)} </script> <script src="/static/bundle.js"></script> </body> </html> ` }
既然有了服务端渲染,为何还要用客户端渲染,因为服务端渲染是“提了裤子不认人”,渲染完,我们的程序就不会动了(因为是一堆字符串),客户端则可以让程序继续动起来,因为客户端有js,可以调用方法重绘浏览器界面。
既然要再渲染一次,为何还要服务端渲染?为了seo,我们的服务端渲染不只是给用户看的,主要是给那些“低能”的网络爬虫看的。
好吧,忍忍火,我们继续工作,客户端再渲染一次。
const initialState = window.__INITIAL_STATE__ const store = configureStore(initialState) const rootElement = document.getElementById(‘app‘) render( <Provider store={store}> <App/> </Provider>, rootElement )
其实客户端渲染也就拿到个初始state,然后render而已,没有很多代码。
我们的state是从window.__INITIAL_STATE__获取的,因为服务端把要给客户端的state放在了这个全局变量上面。
预载state,说得这么“玄乎”,好像很高大上,其实就是把state在服务器那边就生成好,然后传过来直接给客户端用。没有那么“玄乎”。
标签:
原文地址:http://www.cnblogs.com/lewis617/p/5174861.html