为什么使用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. C++的开源跨平台日志库glog学习研究(三)--杂项

    在前面对glog分别做了两次学习,请看C++的开源跨平台日志库glog学习研究(一).C++的开源跨平台日志库glog学习研究(二)--宏的使用,这篇再做个扫尾工作,算是基本完成了. 编译期断言 动态 ...

  2. artTemplate-优秀的前端模板引擎

    artTemplate-优秀的前端模板引擎 1.html中引入artTemplate的js文件: <script type="text/javascript" src=&qu ...

  3. JVM-垃圾收集算法、垃圾收集器、内存分配和收集策略

    对象已死么? 判断一个对象是否存活一般有两种方式: 1.引用计数算法:每个对象都有一个引用计数属性,新增一个引用时计数加1,引用释放时计数减1.计数为0时可以回收. 2.可达性分析算法(Reachab ...

  4. 【C#】override,Abstract,Virtual 介绍及区别--转载

    要扩展或修改继承的方法.属性.索引器或事件的抽象实现或虚实现,必须使用 override 修饰符. 1. override 方法提供从基类继承的成员的新实现.通过 override 声明重写的方法称为 ...

  5. TemplateBinding和Binding的区别

    定义 TemplateBinding是为了某个特定场景优化出来的数据绑定版本--需要把ControlTemplate里面的某个Property绑定到应用该ControlTemplate的控件的对应Pr ...

  6. 自动换行的两种代码(C#)

    最近有个需求,需要将C# winform中的listBox中的内容自动换行, 其实在用listBox前,已经用textBox实现了大部分功能,可惜最后还是有个焦点的问题, 就是textBox中的文字会 ...

  7. SpringMVC源码阅读:视图解析器

    1.前言 SpringMVC是目前J2EE平台的主流Web框架,不熟悉的园友可以看SpringMVC源码阅读入门,它交代了SpringMVC的基础知识和源码阅读的技巧 本文将通过源码(基于Spring ...

  8. MySQL常用命令操作

    1. 命令行登录使用默认3306端口的MySQL: mysql -u root -p 2. 通过TCP连接管理不同端口的多个MySQL(注意:MySQL4.1以上版本才有此项功能): mysql -u ...

  9. JDK动态代理[3]----WeakCache缓存的实现机制

    上一篇我们分析了Proxy类的内部是怎样产生代理类的,我们看到了Proxy内部用到了缓存机制,如果根据提供的类加载器和接口数组能在缓存中找到代理类就直接返回该代理类,否则会调用ProxyClassFa ...

  10. C# linq to xml 简单示例

    data.xml <?xml version="1.0" encoding="utf-8" ?> <Data> <Products ...