为什么使用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. JavaScript中的垃圾回收机制与内存泄露

    什么是内存泄露? 任何编程语言,在运行时都需要使用到内存,比如在一个函数中, var arr = [1, 2, 3, 4, 5]; 这么一个数组,就需要内存. 但是,在使用了这些内存之后, 如果后面他 ...

  2. 线性表 (单链表、循环链表-python实现)

    一.线性表 线性表的定义: 线性表是具有相同数据类型的有限数据的序列. 线性表的特点: 出了第一个元素外,每个元素有且仅有一个直接前驱,除最后一个元素外有且只有一个后继. 线性表是一种逻辑结构,表示元 ...

  3. C#中null值属于什么变量类型

    今天学习发现有段代码的输出结果有些理解不了,如图1,输出的结果全部为 false: 图1 后来和同事讨论研究了一下才明白,原来是这样:↓ class Program { static void Mai ...

  4. Flow中的Switch分析

    A switch statement can complete normally iff at least one of the following is true: (1)The switch bl ...

  5. 一步步用svg做一个声波扩散动画

    有个项目需要在某个坐标显示一个声波扩散(不知道这个表达对不对)的动画. 这种需求一般做法有几种,一种做成gif图片,然后贴上去,一种是用html+css3完成,要么就是画上去,这画又分两种,一种是Ca ...

  6. git工具,conflict冲突解决方法

    这篇文章需要对git具有一定的了解,并且知道如何安装git工具(其实就是上git官网下载个文件,安装) git这种版本控制工具有什么好处 第一个,方便可以多人协同开发同一个项目或系统 第二个,当你系统 ...

  7. 解释mysql 语句 ——解释CREATE DATABASE `test` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci

    在我们创建mysql数据库的时候我们经常会用到这句SQL:CREATE DATABASE `test` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ ...

  8. hibernate原生sql封装,报错信息:could not find setter for rownum_

    今天用hibernate的时候,用了一个原生态sql做了一个分页查询,结果就报错了... 找到解决方法了:http://shmily2038.iteye.com/blog/1704963

  9. 面试题43:计算多少种译码方式(decode-ways)

    这道题是非常典型的DP问题.按照DP的套路,关键是讨论出递推表达式,遍历过程中针对当前字符是否为'0'以及前一个字符为'0',分类讨论得出到目前字符为止最多有多少种译码方式?理清了递推表达式,代码是很 ...

  10. kubernetes continually evict pod when node's inode exhausted

    kubernetes等容器技术可以将所有的业务进程运行在公共的资源池中,提高资源利用率,节约成本,但是为避免不同进程之间相互干扰,对底层docker, kubernetes的隔离性就有了更高的要求,k ...