zoukankan      html  css  js  c++  java
  • React 同构开发(一)

    为什么要做同构

    要回答这个问题,首先要问什么是同构。所谓同构,顾名思义就是同一套代码,既可以运行在客户端(浏览器),又可以运行在服务器端(node)。

    我们知道,在前端的开发过程中,我们一般都会有一个index.html, 在这个文件中写入页面的基本内容(静态内容),然后引入JavaScript脚本根据用户的操作更改页面的内容(数据)。在性能优化方面,通常我们所说的种种优化措施也都是在这个基础之上进行的。在这个模式下,前端所有的工作似乎都被限制在了这一亩三分地之上。

    那么同构给了我们什么样的不同呢?前面说到,在同构模式下,客户端的代码也可以运行在服务器上。换句话说,我们在服务器端就可以将不同的数据组装成页面返回给客户端(浏览器)。这给页面的性能,尤其是首屏性能带来了巨大的提升可能。另外,在SEO等方面,同构也提供了极大的便利。除此以外,在整个开发过程中,同构会极大的降低前后端的沟通成本,后端更加专注于业务模型,前端也可以专注于页面开发,中间的数据转换大可以交给node这一层来实现,省去了很多来回沟通的成本。

    基于React的同构开发

    说了这么多,如何做同构开发呢?
    这还得归功于 React提供的服务端渲染。

    ReactDOMServer.renderToString  
    ReactDOMServer.renderToStaticMarkup
    

    不同于 ReactDom.render将DOM结构渲染到页面, 这两个函数将虚拟DOM在服务端渲染为一段字符串,代表了一段完整的HTML结构,最终以html的形式吐给客户端。

    下面看一个简单的例子:

    // 定义组件 
    import React, { Component, PropTypes } from 'react';
    
    class News extends Component {
    	constructor(props) {
    		super(props);
    	}
    
    	render() {
    		var {data} = this.props;
    		return <div className="item">
          <a href={data.url}>{ data.title }</a>
        </div>;
    	}
    }
    
    export default News;
    

    我们在客户端,通常通过如下方式渲染这个组件:

    // 中间省略了很多其他内容,例如redux等。
    let data = {url: 'http://www.taobao.com', title: 'taobao'}
    ReactDom.render(<News data={data} />, document.getElementById("container"));
    

    在这个例子中我们写死了数据,通常情况下,我们需要一个异步请求拉取数据,再将数据通过props传递给News组件。这时候的写法就类似于这样:

    Ajax.request({params, success: function(data) {
    	ReactDom.render(<News data={data} />, document.getElementById("container"));	
    }});
    
    

    这时候,异步的时间就是用户实际等待的时间。

    那么,在同构模式下,我们怎么做呢?

    // 假设我们的web服务器使用的是KOA,并且有这样的一个controller  
    function* newsListController() {
    	
      const data = yield this.getNews({params});
    
      const data = {
        'data': data
      };
      
      this.body = ReactDOMServer.renderToString(News(data));
    };
    

    这样的话,我么在服务端就生成了页面的所有静态内容,直接的效果就是减少了因为首屏数据请求导致的用户的等待时间。除此以外,在禁用JavaScript的浏览器中,我们也可以提供足够的数据内容了。

    什么原理

    其实,react同构开发并没有上面的例子那么简单。上面的例子只是为了说明服务端渲染与客户端渲染的基本不同点。其实,及时已经在服务端渲染好了页面,我们还是要在客户端重新使用ReactDom.render函数在render一次的。因为所谓的服务端渲染,仅仅是渲染静态的页面内容而已,并不做任何的事件绑定。所有的事件绑定都是在客户端进行的。为了避免客户端重复渲染,React提供了一套checksum的机制。所谓checksum,就是React在服务端渲染的时候,会为组件生成相应的校验和(checksum),这样客户端React在处理同一个组件的时候,会复用服务端已生成的初始DOM,增量更新,这就是data-react-checksum的作用。

    所以,最终,我们的同构应该是这个样子的:

    // server 端  
    function* newsListController() {
    	
      const data = yield this.getNews({params});
    
      const data = {
        'data': data
      };
      let news = ReactDOMServer.renderToString(News(data));
      this.body = '<!doctype html>
    
                          <html>
                            <head>
                                <title>react server render</title>
                            </head>
                            <body><div id="container">' +
                                news +
                                '</div><script>var window.__INIT_DATA='+ JSON.stringify(data) +'</script><script src="app.js"></script>
                            </body>
                          </html>';
    };
    
    // 客户端,app.js中  
    let data = JSON.parse(window.__INIT_DATA__);  
    ReactDom.render(<News props={data} />, document.getElementById("container"));
    
    

    小结

    最近一直在做同构相关的东西,本文主要讨论react同构开发的基本原理和方式,作为一个引子,其中省去了很多细节问题。关于同构应用开发,其实有很多事情要做,比如node应用的发布、监控、日志管理,react组件是否满足同构要求的自动化检测等。这些事情都是后续要一步一步去做的,到时候也会做一些整理和积累。

  • 相关阅读:
    智慧光伏能源-园区光伏发电能源管控可视化
    无人值守,智能变电站可视化管控系统
    数字孪生,开启三维智慧园区管理新篇章
    智慧城市大数据运营中心 IOC 之 Web GIS 地图应用
    三维可视化数据中心机房监控管理系统
    打造绿色城市,数字孪生天然气站 3D 可视化
    绿色物流-智慧仓储监控管理 3D 可视化系统
    打造综合性智慧城市之朔州开发区 3D 可视化
    绿色城市之地下综合管廊3D可视化平台
    工业绿色环保发展:风力发电场管理监测可视化系统
  • 原文地址:https://www.cnblogs.com/bingooo/p/5724354.html
Copyright © 2011-2022 走看看