基于React+Redux的SSR实现

  • 时间:
  • 浏览:2
  • 来源:uu快3手机版_uu快3走势图_网游

注意typeof window !== 'undefined',.我 还也能那我做,因为这段代码也会在服务端执行,这若果为那先 说在做服务端渲染还也能非常小心,尤其是全局使用的浏览器api的前一天。

服务器端呈现是一一另还还有一个 有趣的话题。它有许多优势,并改善了整体用户体验。它后要提升你的单页多多线程 的SEO。但这名 切太大简单。在大多数情况报告下,还也能额外的工具和精心选着的api。

// App.jsx
import React from 'react';
import { connect } from 'react-redux';

import { getUsers } from './redux/selectors';
import { usersFetched } from './redux/actions';

const ENDPOINT = 'http://localhost:4000/users_fake_data.json';

class App extends React.Component {
  componentWillMount() {
    fetchUsers();
  }
  render() {
    const { users } = this.props;

    return (
      <div>
        {
          users && users.length > 0 && users.map(
            // ... render the user here
          )
        }
      </div>
    );
  }
}

const ConnectedApp = connect(
  state => ({
    users: getUsers(state)
  }),
  dispatch => ({
    fetchUsers: async () => dispatch(
      usersFetched(await (await fetch(ENDPOINT)).json())
    )
  })
)(App);

export default ConnectedApp;

总结下来有以下几点:

:

.我 将用babelify转换来使用browserify和watchify来打包.我 的客户端代码。对于.我 的服务器端代码,.我 将直接使用babel-cli。

有了上端的代码,.我 的组件因为还也能成功地在服务器端渲染。通过开发者工具,.我 还也能想看 发送到浏览器的内容:

1、.我 明确知道请求的页面还也能那先 样的数据。.我 获取数据并使用该数据创建Redux存储。也不 .我 通过提供已完成的Store来呈现页面,理论上.我 还也能做到。

这若果一一另还还有一个 简单的案例,实际开发场景往往比这名 繁杂的多,还也能考虑的情况报告也会非常多,.我 的服务端渲染是为什么么做的?

.我 在package.json上端加入以下一一另还还有一个 命令脚本:

为了演示方便,.我 首选Express作为http服务器。

concurrently库帮助并行运行多个多多线程 ,这正是.我 在监控更改时还也能的。

因为重新启动服务器并打开相同的

在这里还也能提的一一另还还有一个 重点是,一旦.我 想实现服务端渲染,那.我 就还也能改变前一天的纯客户端编程模式。

为了能架构设计

.我 使用了相同的组件<App />和 store,不同之居于于它返回的是一一另还还有一个 字符串,而后要虚拟DOM。

目前为止,.我 的服务端仅仅是返回了一一另还还有一个 html骨架,而所有交互全在客户端完成。浏览器还也能先下载bundle.js后执行。而服务端渲染的作用若果在服务器上执行所有操作并发送最终标记,而后要把所有工作交给浏览器执行。React足够的聪明,也能识别出那先 标记。

请求去改变应用情况报告,.我 还也能编写

reducer解决过程如下:

当然,现在并没办法 日后日后开始了,客户端JavaScript他不知道服务器上居于了那先 ,也他不知道.我 因为对API进行了请求。.我 还也能通过传递Store的情况报告来通知浏览器,以便它也能接收它。

fetchUsers是一一另还还有一个 异步函数,它通过Fetch API请求数据。当数据返回时,会架构设计 users_fetch动作,从而通过reducer重新计算情况报告,而.我 的<App />因为连接到Redux从而被重新渲染。

原文作者:感叹句

为那先 直接返回的是工厂函数而后要createStore(reducer)?这因为.我 在服务器端渲染时,.我 还也能一一另还还有一个 全新的Store实例来解决每个请求。

.我 的页面中嘴笨 有许多内容,但它若果<div data-reactroot=""></div>。这太大因为多多线程 出错了。这绝对是正确的。React嘴笨 呈现了.我 的页面,但它只呈现静态内容。在.我 的组件中,.我 在获取数据前一天那先 都没办法 ,数据的获取是一一另还还有一个 异步过程,在服务器上呈现时,.我 还也能考虑到这名 点。这若果.我 的任务变得棘手的地方。这还也能归结为.我 的多多线程 在做那先 。在本例中,客户端代码依赖于一一另还还有一个 特定的请求,但因为使用redux-saga库,则因为是多个请求,因为因为是一一另还还有一个 删改的root saga。我意识到解决这名 现象的两种土最好的法子:

最后一一另还还有一个 有用的命令,用于运行.我 的http服务器:

今天.我 将构建一一另还还有一个 使用Redux的简单的React多多线程 ,实现服务端渲染(SSR)。该示例包括异步数据抓取,这使得任务变得更有趣。

本文来源: 掘金 如需转载请联系原作者

.我 使用Storesubscribe土最好的法子来监听情况报告。当情况报告居于变化——是算不算有任何用户数据被获取。因为users居于,.我 将unsubscribe(),那我.我 就无需让相同的代码运行两次,也不 .我 使用相同的存储实例转换为string。最后,.我 将标记输出到浏览器。

你想看 ,.我 使用componentWillMount来发送fetchUsers请求,componentDidMount为那先 也能用呢? 主要因为是componentDidMount在服务端渲染过程中太大会执行。

store.subscribe土最好的法子返回一一另还还有一个 函数,调用这名 函数就还也能解除监听

在日后日后开始了了编写应用前一天,还也能.我 先把环境编译/打包环境配置好,因为.我 采用的是es6语法编写代码。.我 还也能将代码编译成es5代码在浏览器或node环境中执行。

也不 将这名 字符串加入到Express的响应上端,许多服务端代码为:

<html>
          <head>
            <title>App</title>
            <style>
              body {
                font-size: 18px;
                font-family: Verdana;
              }
            </style>
          </head>
          <body>
            <div id="content"><div data-reactroot=""><p>Eve Holt</p><p>Charles Morris</p><p>Tracey Ramos</p></div></div>
            <script>
              window.__APP_STATE = {"users":[{"id":4,"first_name":"Eve","last_name":"Holt","avatar":"https://s3.amazonaws.com/uifaces/faces/twitter/marcoramires/128.jpg"},{"id":5,"first_name":"Charles","last_name":"Morris","avatar":"https://s3.amazonaws.com/uifaces/faces/twitter/stephenmoon/128.jpg"},{"id":6,"first_name":"Tracey","last_name":"Ramos","avatar":"https://s3.amazonaws.com/uifaces/faces/twitter/bigmancho/128.jpg"}]};
            </script>
            <script src="/bundle.js"></script>
          </body>
        </html>

服务器端渲染,也叫代码同构,也若果同一份代码既能在客户端渲染,又能在服务端渲染。

2、.我 删改依赖于运行在客户端上的代码,计算出最终的结果。

.我 还也能保证代码能在服务端正常的运行。同类,访问Window对象,Node不提供Window对象的访问。

有了这名 文件,.我 还也能运行npm run start并访问http://localhost:4000。.我 想看 数据获取成功,并成功的显示了。

同类,.我 使用了Fetch API向后端发出异步请求,而服务端默认是不支持的。.我 还也能做的若果在server.js中将Fetch导入:

实现的最关键一步若果创建

假设服务端返回以下的数据格式:

最后一一另还还有一个 还也能优化的地方,若果当因为取到users时,还也能阻止fetch

第两种土最好的法子,还也能.我 在两端做好情况报告管理。第二种土最好的法子还也能.我 在服务端使用许多额外的库或工具,来确保同一套代码能在服务端和客户端做相同的事情,我自己比较推荐使用这名 土最好的法子。

服务端几乎相同:

import ReactDOM from 'react-dom';

ReactDOM.render(
  <Provider store={ createStore() }><App /></Provider>,
  document.querySelector('#content')
);

.我 通过一一另还还有一个 组件将数据渲染出来。在这名 组件的componentWillMount生命周期土最好的法子中,.我 将触发数据获取,一旦请求成功,.我 将发送一一另还还有一个 类型为user_fetch的操作。该操作将由一一另还还有一个 reducer解决,.我 将在Redux存储中获得更新。情况报告的改变将触发.我 的组件重新呈现指定的数据。

代码形态学 如下:

还记得.我 在客户端做的以下事情吗?

因为您想使用本文中讨论的代码,请查看GitHub: answer518/react-redux-ssr

,.我 将想看 以下响应:

不使用node ./build/server/server.js而使用Nodemon的因为是,它还也能监控.我 代码中的任何更改,并自动重新启动服务器。这名 点在开发过程会非常有用。

.我 使用客户端API接收异步数据,一旦Store获取到异步数据,.我 将触发ReactDOMServer.renderToString。它会提供给.我 我应该 的标记。.我 的Express解决器是那我的: