Genluo / Precipitation-and-Summary

梳理体系化的知识点&沉淀日常开发和学习
MIT License
16 stars 1 forks source link

CSR(Client Side Rendering)网页首帧优化总结 #33

Open Genluo opened 5 years ago

Genluo commented 5 years ago

前言

我们发现随着javascript的出现优化前端开发流程,同时也为前端开发带来新的问题,一个典型的问题就是使用CSR(客户端渲染)出现的首屏白屏问题,首屏白屏将极大的影响用户的操作体验所以为了解决这个问题,我们分析react实现和浏览器渲染页面的相关过程,我们提出如下几种解决方案:

下面我们将依次介绍这几种解决方案,通过对比这几种方法,我们找出最适合项目的解决方案。

CSR(Client Side Rendering)

CSR就是:html 仅仅作为静态文件,客户端端在请求时,服务端不做任何处理,直接以原文件的形式返回给客户端客户端,然后根据 html 上的 JavaScript,生成 DOM 插入 html,这就是问题产生的根源,因为浏览器需要执行js才能生成DOM并且将产生的DOM插入到html,但是结合网络性能和客户端渲染相关规则,所以造成首屏白屏问题,为了解决这个问题,我们将通过几种方法来解决这个问题,但是为什么不直接选择不使用CSR?

服务器渲染流程图

为什么不直接不是使用CSR方案?

SSR(server side render)

这种指传统的 ASP、Java 或 PHP 的渲染机制;比如说cnode.js这个项目,这个和客户端渲染中的同构渲染是两个不同的概念,一个对应的是传统 Java、PHP 或 ASP 的渲染机制,另一种则是使用 node.js(理论上可以使用其他语言)把在客户端使用的组件在服务端渲染成 HTML 文本。

服务器端渲染的有优点

预渲染

这里主要说下美团网 - 最佳实践,下面是美团网预渲染流程图

预渲染流程图

我们将整个页面整个页面渲染分成三个部分,FP(First Paint)、FCP(First Contentful Paint)、FMP(First Meaningful Paint),常规CSR三个阶段中FP通常只有一个根节点,FCP阶段包含页面的基本框架,但是没有数据内容,FMP阶段通常包含页面所有元素及其数据。CSR出现的白屏问题就是在FP阶段出现的问题,如果我们能将FCP或者FMP渲染生成的html文档提前到FP阶段进行渲染,用户就能够看到页面框架,也就不会出现相应的白屏问题。- 预渲染思路

为了实现这种预先渲染的方案,那么我们需要使用node作中间层,在项目构建编译时,完成对原始模板的更新和替换,整个项目的流程入下:

开发阶段:

发布阶段:

自己的思考

但是我认为这种方式治标不治本,因为我们通过将FCP阶段产生的内容提前到FP阶段中,但是这种方式并不能和动态数据进行交互,所以如果整个页面都是静态数据,那么这种方式是完美的,但是如果整个页面或者页面的部分是需要获取动态数据的,那么这样我们发现这种开发方式并不是十分完美的,因为仍有可能造成页面因为数据而抖动,所以我认为预渲染并没有在本质上解决这个问题。

同构

同构是为了解决CSR遇见的问题才出现的,同构是14年出现,成为当时框架一大亮点,同构是针对单页应用SEO优化乏力,首屏速度瓶颈等问题而产生的解决方案,近年来在react和Vue等前端技术栈中都得到了支持,同构是客户端首次请求进行服务器端渲染,结合缓存处理来解决首屏速度瓶颈问题。

React实现同构的过程

核心是React中拥有虚拟DOM的概念,因为存在虚拟DOM,所以React可以脱离浏览器进行渲染,相关流程如下:

服务器端渲染需要把React的初次渲染放到服务器,让React帮我们把业务Component翻译成string类似的DOM,然后通过IO返回给到客户端。

我们来看 React 官方给我们提供的服务端渲染的API:

配合 renderToStringrenderToStaticMarkup 使用,createElement 返回的 ReactElement 作为参数传递给前面两个方法。那么我们要实现同构渲染主要解决这几个问题:

实现React作为服务器端渲染的中间件

首先为了实现服务器端渲染需要封装一个中间件,实现React的后端渲染,调用React的服务器端渲染方法生成对应的字符串,然后组装放回给客户端请求。

实现React-router 和后端router统一
实现异步数据的处理
同构带来的好处:
  1. 有助于 SEO
  2. 共用前端代码,节省开发时间
  3. 提高首屏性能
同构带来的坏处:
  1. 性能
  2. 不容忽视的服务器端和浏览器环境差异
  3. 内存溢出
  4. 异步操作
  5. simple store(redux)
总结

同构这种方式结合CSR和SSR的所有优点,但是也带来新的问题,并且在大型项目中存在一个严重的问题就是Node中很容易成为性能瓶颈,所以大型项目一般不采用同构渲染

自己理想的方式

理想的方式将预渲染和视觉优化结合起来进行预分析,不要使用同构方法,同构的方法带来的问题很大,对于整个项目侵入性很大,

视觉优化

其实针对上述白屏问题,我们也可以通过视觉进行优化,比如可以通过

  1. 分拆打包
  2. 交互优化:使用loading的效果、Skeleton Screen 效果
  3. 部分同构化处理

Next.js 优化总结

Next.js 是时下非常流行的基于 React 的同构开发框架。作者之一就是大名鼎鼎的 Socket.io 的作者 Guillermo Rauch。它有以下几个亮点特别吸引我:

  1. 巧妙地用标准化的解决了请求的问题。同构和页面开发类似,异步是个大难题,异步中难点又在接口请求。Next.js 给组件新增了 getInitialProps 方法来专门处理初始化请求,再也不用手动往页面上塞 DATA 和调用 ReactDOMServer.renderToString
  2. 使用 styled-jsx 解决了 css-in-js 的问题。这种方案虽然不像 styled-component 那样强大,但足够简单,可以说是最小的成本解决了问题
  3. Fast by default。页面默认拆分文件方式打包,支持Prefetch页面预加载

相关资料

Genluo commented 2 years ago

Astro 相比 Next.js 可以大幅度减少 JS 代码的体积(90% 以上),同时页面的运行时性能也提升了 30% 以上。除此之外,Astro 不仅支持使用 React 框架,而且支持 Vue、Solid 等在内的各种前端框架,灵活性更高。

https://mp.weixin.qq.com/s/G7b9Dv5xEvnM0AMT1EXKJQ