服务端渲染之-ssr同构

什么是同构

一份代码,先通过服务端渲染(server-side rendering,ssr),生成html字符串以及初始化数据,客户端拿到后,通过对html的dom进行patch和事件绑定对dom进行客户端激活(client-side hydration,csh),这个整体的过程叫同构渲染。

同构产生的背景 / 同构能够解决单纯客户端渲染的哪些痛点?

1.客户端渲染带来的的首屏白屏时间过长:

         在 SPA 模式下,所有的数据请求和 Dom 渲染都在浏览器端完成,所以当我们第一次访问页面的时候很可能会存在“白屏”等待,而服务端渲染所有数据请求和 html内容已在服务端处理完成,浏览器收到的是完整的 html 内容,可以更快的看到渲染内容。

         2. 客户端渲染不利于SEO:

         由于现阶段大多搜索引擎采用的爬虫算法是直接抓取页面代码分析,而SPA应用只有一个入口文件而没实质内容,SEO性能差。

适用的场景?

          1.特别依赖搜索引擎流量的项目;

2.对首屏时间有特殊要求;

现有的的开源框架?

next.js、react server、Beidou(北斗) 、

核心原理及架构流程图?

          借助虚拟DOM的特性,将一份代码在服务端和客户端各执行一次:

1、服务端使用 react-dom包提供的 server端渲染api: renderToString (常用)或 renderToStaticMarkup直接渲染出包含页面信息的静态 html字符串。

          2、客户端根据渲染出的静态 html 进行二次渲染,做一些绑定事件等交互操作。

同构的缺点?    

          1.同构会增加服务器的负载,对此一般推荐对于首屏和个别页面进行SSR服务端的渲染,此外仍保持应用为客户端SPA,充分利用浏览器特点,达到最优性能。

          2.使原本简单的 React 项目变得非常复杂,项目的可维护性会降低,代码问题的追溯也会变得困难。所以,使用 SSR 在解决问题的同时,也会带来非常多的副作用,有的时候,这些副作用的伤害比起 SSR 技术带来的优势要大的多。

关键点?

 1.双端框架选择:

           客户端:react(v16+)

           服务器端:koa/express

2.环境区分

           同一套代码在客户端和服务端执行两次,但因为环境不同,有些对象是不自带的,要加以区分避免出现问题。像前端特有的 Window 对象,Ajax 请求 在后端是无法使用上的,后端需要去掉这些前端特有的对象            逻辑或使用对应的后端方案,如后端可以使用 http.request 替代 Ajax 请求,所以需要进行平台区分,主要有以下几种方式:

          1. 代码使用前后端通用的模块,如 isomorphic-fetch

          2. 前后端通过 webpack 配置 resolve.alias 对应不同的文件

          3. 使用 webpack.DefinePlugin 在构建时添加一个平台区分的值

  3.react服务端提供的渲染API

  React 之所以可以做到服务端渲染 就是因为react-dom/server提供了服务端渲染的API。

renderToString 同步地把一个react 元素转换成带html字符串,遇到复杂页面时用户等待时间也不短。

renderToNodeStream把渲染结果以‘流’的形式返回给浏览器端,用户体验更友好。

后续为了客户端在渲染组件时,最大限度地保留在服务端使用 renderToString 生成的内容结构,ReactDom 相应的在客户端提供了一个新的 API:hydrate。

4.路由同构

首先需要抽离出一份路由组件文件routes.js:

客户端使用 react-router-dom 下的 BrowserRouter 进行前端路由控制。

服务端使用 react-router-dom 下的 StaticRouter 进行静态路由控制。

使用 react-router-config 下的 matchRoutes 匹配后端路由,使用 renderRoutes 渲染匹配到的路由。

使用 react-router-dom/server 下的 renderToString 方法,渲染出 html 字符串,并返回给前端。

使用 StaticRouter 中通过 context 可以和前端页面通信,传参。

数据交互与状态同步?

可以选用redux实现数据状态的同步:在服务端通过组件的静态API方法获取接口数据后创建store,再通过 window.store= store 传递给前端;此时应用中的所有页面都可以共享使用store中的数据,可以使用dispatch方法进行交互。

双端打包差异?

客户端打包:

          服务端打包:

你可能感兴趣的:(服务端渲染之-ssr同构)