React 服务器端渲染流程
其实我们在访问客户端渲染的页面时,请求到的只是一个 html 空壳,里面引入了一个 js 文件,所有的内容都是通过 js 进行插入的,正是因为页面是由 js 渲染出来的,所以会带来如下几个问题:
1、页面要等待 js 加载,并执行完成了才能展示,在这期间页面展现的是白屏
。
2、爬虫不能识别 js 内容,所以抓取不到任何数据,不利于 SEO 优化
。
那如果请求到的直接是一个渲染好的页面,是不是就可以解决这 2 个问题了呢?
没错,服务器端渲染就是这个原理。
简化流程
1、服务器端使用 renderToString 直接渲染出包含页面信息的静态 html
。
2、客户端根据渲染出的静态 html 进行二次渲染
,做一些绑定事件等操作。
服务器端没有 DOM,Window 等概念,所以只能渲染出字符串,不能进行事件绑定,样式渲染等。
只有第一次访问页面时才使用服务器端渲染,之后会被客户端渲染接管。
开始写代码吧
接下来我们一起来写一个 React 服务器端渲染 Demo。
编写路由
这里使用 react-router 对前后端代码进行同构。
1、客户端
使用 react-router-dom 下的 BrowserRouter
进行前端路由控制。
2、服务器端
使用 react-router-dom 下的 StaticRouter
进行静态路由控制,具体操作如下:
- 使用 react-router-config 下的 matchRoutes 匹配后端路由,使用 renderRoutes 渲染匹配到的路由。
- 使用 react-router-dom/server 下的 renderToString 方法,渲染出 html 字符串,并返回给前端。
使用 StaticRouter 中通过 context 可以和前端页面通信,传参。
状态管理
在 React 中,我们常常使用 redux 来存储数据,管理状态。
1、客户端
使用 redux 进行状态管理,使用 react-redux 提供的 Provider 为组件注入 store。
2、服务器端
和客户端一样,但每一次接收到请求需产生一个新的 store,避免多个用户操作同一个 store。
数据请求
1、客户端
使用 axios 在 componentDidMount 中请求数据。
2、服务器端
同样使用 axios 去请求数据,但是服务器端不会触发 componentDidMount 生命周期。我们可以在后端匹配到路由的时候,进行数据请求,并把数据存入 redux 中的 store,然后渲染出包含数据的 html 页面,为了避免客户端二次请求,服务器端向 window 中注入 REDUX_STORE 数据,客户端直接使用此数据作为客户端 redux 的初始数据,以免发生数据抖动。
具体操作如下:
- 在 routes 对象上挂载一个自定义方法 loadData。
- 在服务器端 matchRoutes 后,如果有 loadData,则进行请求数据,并把请求到的数据写入 store 中。
- 服务器端等待请求完成后,再进行 renderToString 渲染。
样式处理
1、客户端
使用 css-loader,style-loader 打包编写好的 css 代码并插入到页面中。
2、服务器端
由于 style-loader 会插入到页面,而服务器端并没有 document 等概念,所以这里使用 isomorphic-style-loader 打包 css 代码。
- 引入 isomorphic-style-loader 后,客户端就可以通过 styles._getCss 方法获取到 css 代码。
- 通过 staticRouter 中的 context 把 css 代码传入到后端。
- 后端拼接好 css 代码,然后插入到 html 中,最后返回给前端。
SEO 优化
SEO 主要是针对搜索引擎进行优化,为了提高网站在搜索引擎中的自然排名,但搜索引擎只能爬取落地页内容(查看源代码时能够看到的内容),而不能爬取 js 内容,我们可以在服务器端做优化。
常规的 SEO 主要是优化:文字
,链接
,多媒体
- 内部链接尽量保持相关性
- 外部链接尽可能多
- 多媒体尽量丰富
由于网页上的文字,链接,图片等信息都是产品设计好的,技术层面不能实现优化。我们需要做的就是优化页面的 title,description 等,让爬虫爬到页面后能够展示的更加友好。
这里借助于 react-helmet 库,在服务期端进行 title,meta 等信息注入。
你可能不需要服务器端渲染?
现在,我们成功地通过服务器端渲染解决了首次加载白屏时间
和 SEO 优化
。但也带来了一些问题:
- 服务器端压力增大。
- 引入了 node 中间层,可维护性增大。
以上两个问题归根结底还是钱的问题。服务器压力大,可以通过买更多的服务器来解决。可维护性增大,可以招募更多人来维护。但是对于小型团队来说,增加服务器,招募更多维护人员,都会额外增加的支出,所以在选择服务器端渲染时,要权衡好利弊。
解决 SEO 的另一种方法
如果只是想优化 SEO,不妨使用预渲染来实现,推荐使用 prerender 库来实现。
prerender 库的原理:先请求客户端渲染的页面,把客户端渲染完成之后的结果,拿给爬虫看
,这样爬虫获取到的页面就是已经渲染好的页面。prerender 库在使用时会开启一个服务,通过传递 url 来解析客户端渲染页面,这就需要我们对服务器端架构进行调整。
1、 nginx 判断访问类型
2.1、 用户访问 :直接走客户端渲染
2.2、 爬虫访问 :走预渲染
React 服务器端渲染流程的更多相关文章
- 基于React服务器端渲染的博客系统
系统目录及源码由此进入 目录 1. 开发前准备 1.1 技术选型1.2 整体设计1.3 构建开发 2. 技术点 2.1 react2.2 redux, react-router2.3 server-r ...
- 玩转 React 服务器端渲染
React 提供了两个方法 renderToString 和 renderToStaticMarkup 用来将组件(Virtual DOM)输出成 HTML 字符串,这是 React 服务器端渲染的基 ...
- React服务器端渲染值Next.js
昨天leader给分配了新任务,让熟悉一下ssr,刚开始有点懵,啥玩意?百度了一下,不就是服务器端渲染(server side render,简称: ssr). ssr简介 服务端渲染一个很常见的场景 ...
- React服务器端渲染框架next.js项目实战及部署上下文context问题解决办法
在前段时间折腾过搭建react服务器端项目架构,点击这里了解下,正好最近有个重构PC网站的需求,考虑SEO等因素.在做技术选型的时候决定采用nextjs.项目开发过程中,nextjs的体验非常棒,个人 ...
- react 服务器端渲染 ssr 中 localstorage/history/window is not defined 解决方案
1.原因 ssr 会在后端执行组件的 componentWillMount 以及在它这个生命周期之前的生命周期 也就是说 ssr 阶段是不会执行 componentDidMount 方法的 当你在 c ...
- react16 渲染流程
前言 react升级到16之后,架构发生了比较大的变化,现在不看,以后怕是看不懂了,react源码看起来也很麻烦,也有很多不理解的地方. 大体看了一下渲染过程. react16架构的变化 react ...
- react实现ssr服务器端渲染总结和案例(实例)
1.什么是 SSR SSR 是 server side render 的缩写,从字面上就可以理解 在服务器端渲染,那渲染什么呢,很显然渲染现在框架中的前后端分离所创建的虚拟 DOM 2.为什么要实现服 ...
- react 16 Hooks渲染流程
useState react对useState进行了封装,调用了mountState. function useState<S>( initialState: (() => S) | ...
- 【大前端之前后分离01】JS前端渲染VS服务器端渲染
前言 之前看了一篇文章:@Charlie.Zheng Web系统开发构架再思考-前后端的完全分离,文中论述了为何要前后分离,站在前端的角度来看,是很有必要的:但是如何说服团队使用前端渲染方案却是一个现 ...
随机推荐
- finereport 通过条件弹出 alert进行提示
function convertDateFromString(dateString) { if (dateString) { var date = new Date(dateString.replac ...
- 蓝鲸-监控 排错思路 - 原理push - bkdata报错 - saas的日志
1.现象和报错 .[10.253.124.21] paas_agent() paas_agent FATAL Exited too quickly (process log may have deta ...
- SolidWorks学习笔记2草图
几何约束 显示和隐藏约束 单个直线的约束 绘制一个直线,点击左侧的中的水平或者竖直,, 如果要删除改约束,右键绿色的小矩形,相关被约束的对象变成分红,点击删除即可. 两个对象之间的约束 点击一个对象, ...
- C# XML操作之一:使用XmlDocument来读写
所有代码都在同一个类中,含有对象 XmlDocument doc = new XmlDocument(); 新建XML,并且写入内容 private void button4_Click(object ...
- 在phpStrom中安装php代码格式化插件Php-cs-fixer
由于phpStrom原来的插件不再开源,现在转为使用Php-cs-fixer格式化代码.以下为在phpStrom中安装Php-cs-fixer的具体步骤. 安装安装很简单,下载php-cs-fixer ...
- 手把手教你用 Strace 诊断问题
早些年,如果你知道有个 strace 命令,就很牛了,而现在大家基本都知道 strace 了,如果你遇到性能问题求助别人,十有八九会建议你用 strace 挂上去看看,不过当你挂上去了,看着满屏翻滚的 ...
- PTA(Basic Level)1014.福尔摩斯的约会 && PTA(Advanced Level)1061.Dating
大侦探福尔摩斯接到一张奇怪的字条:我们约会吧! 3485djDkxh4hhGE 2984akDfkkkkggEdsb s&hgsfdk d&Hyscvnm.大侦探很快就明白了,字条上奇 ...
- 制作U盘的win7系统安装
方法一 用iso.需要下载个UltraISO软件安装. 制作64位WIN7系统U盘安装盘方法 首页就有iso下载,有雨林木风等,我下载了系统之家最新的1907 U盘安装win7系统BIOS设置 thi ...
- sql server之批量数据导入
实际应用场景中,有时会需要把一批数据导入数据库.这批数据可能来源于另一个数据源.比较常规的做法是先读取到dataset,然后跑一个循环,每一行拼一句insert into语句,执行之.用过的人会知道, ...
- 2017.10.28 C组比赛总结
这次比赛有点坑... [GDKOI2004]石子游戏 方法:判断奇偶性 输入n 如果n是奇数,输出 xiaoshi 如果n是偶数,输出 xiaoyong 比赛得分:30 错因:找错规律了(忘记了两个人 ...