为什么使用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. 剑指offer二十四之二叉树中和为某一值的路径

    一.题目 输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径.路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径. 二.思路 详见代码 三.代码 1.解答代码 im ...

  2. (转)AWK函数

    http://wiki.jikexueyuan.com/project/awk/built-in-functions.html-------内置函数 http://wiki.jikexueyuan.c ...

  3. sublime text ubuntu

    { "color_scheme": "Packages/User/SublimeLinter/Dawn (SL).tmTheme", "font_fa ...

  4. python3 判断大小端的一种方法

    这里用到了array.array('H', [1])来测试大小端,[1]可以转化为十六进制的0x0001,占两位,00位高位, 01位低位,通过第一位就可以判断大小端. 如果是小端,则转化为bytes ...

  5. linux把程序添加到全局环境变量

    比如把, nginx服务放到全局变量 ln -s /usr/local/nginx/sbin/nginx /usr/local/bin/ /usr/local/bin/就是环境变量目录

  6. Asp.Net Core 连接Mysql

    上一篇文章里最后在VS里测试是没有问题的,但是在Windows命令行模式下会报错. 首先用dotnet restore命令的时候会出现error: 然后用dotnet run会出现警告,但是依旧会成功 ...

  7. 【数组】Container With Most Water

    题目: Given n non-negative integers a1, a2, ..., an, where each represents a point at coordinate (i, a ...

  8. Android中的各种访问权限Permission含义

    android.permission.EXPAND_STATUS_BAR 允许一个程序扩展收缩在状态栏,android开发网提示应该是一个类似Windows Mobile中的托盘程序 android. ...

  9. 图解-安卓中调用OpenGL

    游戏开发中经常使用到OpenGL,当然很多人都喜欢直接用现有的游戏引擎,但相信了解的更多对你没有坏处 安卓开发中,采用的OpenGL ex2的规范,前几天看了下这个规范,整体上难度比1.0规范难度加大 ...

  10. unity游戏开发之entitas框架

    框架介绍 entitas是一个超快.超轻量的c# Entity-Component-System (ECS)框架,专门为Unity引擎设计.提供内部缓存和高速的组件访问,经过精心设计,可以在垃圾收集环 ...