为什么使用SSR

与传统 SPA(Single-Page Application - 单页应用程序)相比

服务器端渲染(SSR)的优势主要在于:

  • 更好的 SEO,由于搜索引擎爬虫抓取工具可以直接查看完全渲染的页面。
请注意,截至目前,Google 和 Bing 可以很好对同步 JavaScript 应用程序进行索引。在这里,同步是关键。如果你的应用程序初始展示 loading 菊花图,然后通过 Ajax 获取内容,抓取工具并不会等待异步完成后再行抓取页面内容。也就是说,如果 SEO 对你的站点至关重要,而你的页面又是异步获取内容,则你可能需要服务器端渲染(SSR)解决此问题。
 
  • 更快的内容到达时间(time-to-content),特别是对于缓慢的网络情况或运行缓慢的设备。
无需等待所有的 JavaScript 都完成下载并执行,才显示服务器渲染的标记,所以你的用户将会更快速地看到完整渲染的页面。通常可以产生更好的用户体验,并且对于那些「内容到达时间(time-to-content)与转化率直接相关」的应用程序而言,服务器端渲染(SSR)至关重要。

使用服务器端渲染(SSR)时还需要有一些权衡之处:

  • 开发条件所限。
浏览器特定的代码,只能在某些生命周期钩子函数(lifecycle hook)中使用;一些外部扩展库(external library)可能需要特殊处理,才能在服务器渲染应用程序中运行。
  • 涉及构建设置和部署的更多要求。
与可以部署在任何静态文件服务器上的完全静态单页面应用程序(SPA)不同,服务器渲染应用程序,需要处于 Node.js server 运行环境。
  • 更多的服务器端负载。
在 Node.js 中渲染完整的应用程序,显然会比仅仅提供静态文件的 server 更加大量占用 CPU 资源(CPU-intensive - CPU 密集),因此如果你预料在高流量环境(high traffic)下使用,请准备相应的服务器负载,并明智地采用缓存策略。
 

具体流程

1、webpack打包生成bundle.js并注入生成的html模板

webpack会从入口index.js将内容打包为一个bundle.js文件然后注入到html模板中,通常将该模板放在app的view中以供node渲染。

2、babel将src文件夹中的内容转换为node能识别的内容

因为src中的jsx所用的import和export等node不能识别,需要被转换成required。被转换后的内容放在dist文件夹中。

3、用户访问某路径时将该页面renderToString后的结果注入进相关html模板

// www.test.com/show
await this.ctx.renderSSR('show.html', { App, rootReducer, initState, useRem: true });
  • node读取dist中show的app.js(之前是app.jsx)
  • node获取后端数据
  • 将后端数据作为初始数据传入reducer并生成store,通过Provie传入<App />
  • 将<App />通过renderToString生成字符串注入html模板
  • 将拿到的初始数据作为window._init_data传到前端
<div id='app'>{{ stringData || '' }}</div>
<script>window._initData={{ initData || '' }}</script>
<script src="bundle.js"></script>
  • 将该模板响应给浏览器

4、前端render

浏览器拿到html开始从头解析,将之前的字符串模板渲染成DOM。执行到最后有一个bundle.js然后进入src的index.js执行ReactDOM.render,render的时候会采用diff算法和之前渲染成功的DOM做比对。
前端用全局的_init_data来作为初始化数据传入reducer生成客户端store,之后的action都在前端做,和后端的redux没关系了。
 

总结

如果是spa的话那么是这样的:
<div id="app"></div>
<script src="bundle.js"></script>
 
我们的页面是不支持SEO的,因为该页面被响应到了浏览器之后再由浏览器解析js动态生成页面。为了支持SEO,我们应该在服务器端通过renderToString方法将页面的主屏内容生成字符串插入id为app的div里。将页面的初始数据通过全局变量传入,类似这样:
<div id='app'>{{ stringData || '' }}</div>
<script>window._initData={{ initData || '' }}</script>
<script src="bundle.js"></script>
 
通过这样的方式可以实现SEO,但是仅仅是支持首屏SEO。如果我们有前端路由跳转,那么路由跳转后的页面时不能被SEO的,所以我们要这样:
// node
app.get('/index|/login|/rules', controller.index.rend);
 
当用户通过h5方式做跳转时,每次访问的url都返回同一个html,可以达到每一个路由的SEO。

react-ssr的更多相关文章

  1. React SSR in Action

    React SSR in Action react render HTML string from the server ReactDOMServer https://reactjs.org/docs ...

  2. 浅谈前端nuxt(ssr)

    SSR: 服务端渲染(Server Side Render),即:网页是通过服务端渲染生成后输出给客户端. 一.那为什么要使用SSR呢? 我用一句话理解的就是降低SPA(Single Page App ...

  3. 教你如何在React及Redux项目中进行服务端渲染

    服务端渲染(SSR: Server Side Rendering)在React项目中有着广泛的应用场景 基于React虚拟DOM的特性,在浏览器端和服务端我们可以实现同构(可以使用同一份代码来实现多端 ...

  4. Next.js & SSR & CSR & SG

    Next.js & SSR & CSR & SG getStaticPaths, getStaticProps, getServerSideProps getStaticPro ...

  5. 今天聊一聊nuxt.js(上)

    背景 近期在做内部系统的重构,从一线业务彻底的重构,经过充分的考虑我们准备把这个项目打造成前台业务的试验站,比如ssr和一些其他的前沿技术的探索,积累充分的经验后待合适的契机应用到C端的项目中. 既然 ...

  6. 一年半前端工作经验试水杭州:我是如何拿下网易、阿里和滴滴 offer 的

    前言 笔者毕业于东北大学,大学毕业社招进入环球网,前端开发工程师一职.技术栈:React+node,Github 地址 成果 来到杭州的目标非常的明确,大厂.其实就是网易.阿里和滴滴.好在基本三家都拿 ...

  7. [Next] 服务端渲染知识补充

    渲染 渲染:就是将数据和模版组装成 html 客户端渲染 客户端渲染模式下,服务端把渲染的静态文件给到客户端,客户端拿到服务端发送过来的文件自己跑一遍 js,根据 JS 运行结果,生成相应 DOM,然 ...

  8. 傻傻分不清之 Cookie、Session、Token、JWT

    傻傻分不清之 Cookie.Session.Token.JWT 什么是认证(Authentication) 通俗地讲就是验证当前用户的身份,证明“你是你自己”(比如:你每天上下班打卡,都需要通过指纹打 ...

  9. Node.js _dirname & path All In One

    Node.js _dirname & path All In One file path 相对路径 绝对路径 _dirname https://nodejs.org/docs/latest/a ...

  10. why 2020 you should create a new modern website with web fullstack

    why 2020 you should create a new modern website with web fullstack Full-Stack Web Development Front- ...

随机推荐

  1. 《构建之法》阅读笔记06-项目经理PM

    软件团队里除了能写代码.测试代码和画图做设计的成员,还有一类角色,不做上面这些事情但也很重要,我们叫他们项目经理--PM. PM 的M 就是 Manager: P有这几种: Product Manag ...

  2. Windows下PATH等环境变量详解

    在学习JAVA的过程中,涉及到多个环境变量(environment variable)的概念,如PATH.正确地配置这些环境变量,是能够顺利学习.开发的前提.而经常出现的问题是:有的学习者能够按照提示 ...

  3. 【转】Spark源码分析之-Storage模块

    原文地址:http://blog.csdn.net/aiuyjerry/article/details/8595991 Storage模块主要负责数据存取,包括MapReduce Shuffle中间结 ...

  4. Python -- 数据库连接

    1.连接MySQL(x64系统装不上x32版本) MySQL现在都不支持Python3 import MySQLdb con = MySQLdb.connect(host='127.0.0.1', u ...

  5. libnetwork插件化网络功能

    Docker把网络跟存储这两部分的功能实现都以插件化形式剥离出来,允许用户通过指令来选择不同的后端实现.这也是Docker希望构建围绕着容器的强大生态系统的一些积极的尝试.剥离出来的独立容器网络项目叫 ...

  6. vuex数据管理-数据适配

    由于接口在上线前,不可避免的会出现变动,小则属性名变,大则结构变化.如果处理不当,结构变化时,视图的代码也需要做相应的更改,然后就是容错方法的变动,接着重新自测等,这样,变化成本随着结构的复杂度大大加 ...

  7. 使用ichartjs进行布局图表页面

    先说官网  http://www.ichartjs.com/ 进入里面会有一个可视化布局系统,布局起来自己想要的样式快捷方便,和bootstrap可视化布局系统是一个道理的.

  8. 常用工具说明--Java的常用工具

    1.Eclipse.IntelliJ IDEA Eclipse是IDE领域的瑞士军刀,有着大量定制的接口和无数的插件.它无处不在,后面本文将推荐的其他所有工具都提供Eclipse插件. Eclipse ...

  9. AspxGridView中行的双击事件

    ClientSideEvents-RowDblClick="clike" function clike(s, e) {           grdList.GetRowKey(e. ...

  10. Spring Security 源码解析(一)

    上篇 Spring Security基本配置已讲述了Spring Security最简单的配置,本篇将开始分析其基本原理 在上篇中可以看到,在访问 http://localhost:18081/use ...