乐趣区

关于ssr:CSR和SSR更新中

前言

当初的 web 网站都是十分考究用户体验,个别都会采纳服务端渲染加客户端渲染一起实现性能。服务端渲染有利于搜索引擎优化(SEO),利于被网页爬虫抓取数据,多见于电商网站商品信息获取等。客户端渲染不利于搜索引擎优化,网页数据异步获取,首页加载工夫长,用户体验绝对较好,罕用于不须要对 SEO 敌对的中央

内容

1. 服务端渲染(SSR)

简略了解就是浏览器发送申请后,服务器把客户端网页和数据在后盾渲染解析,之后把渲染后的后果返回客户端。服务器端渲染的页面交互能力无限,如果要实现简单交互,还是要通过引入 JavaScript 文件来辅助实现。

客户端拿到的是渲染后的后果,能够间接展现。服务器端渲染的页面在网络中传输的时候,传输的是一个实在的页面。因而,爬虫客户端当爬到咱们的页面后,会分系咱们给他提供的这个页面,此时,咱们页面中的要害数据就会被爬虫给收录了。服务端渲染能够解决首页白屏工夫过久,然而也容易导致服务器压力大,因而,能够应用服务器端的页面缓存技术,加重服务器的渲染压力。

流程

让 React 代码在服务器端先执行一次,使得用户下载的 HTML 曾经蕴含了所有的页面展现内容,这样,页面展现的过程只须要经验一个 HTTP 申请周期,TTFP 工夫失去一倍以上的缩减。同时,因为 HTML 中曾经蕴含了网页的所有内容,所以网页的 SEO 成果也会变的十分好。之后,咱们让 React 代码在客户端再次执行,为 HTML 网页中的内容增加数据及事件的绑定,页面就具备了 React 的各种交互能力。

实现原理

下面咱们说过,SSR 的工程中,React 代码会在客户端和服务器端各执行一次。你可能会想,这没什么问题,都是 JavaScript 代码,既能够在浏览器上运行,又能够在 Node 环境下运行。但事实并非如此,如果你的 React 代码里,存在间接操作 DOM 的代码,那么就无奈实现 SSR 这种技术了,因为在 Node 环境下,是没有 DOM 这个概念存在的,所以这些代码在 Node 环境下是会报错的。

好在 React 框架中引入了一个概念叫做虚构 DOM,虚构 DOM 是实在 DOM 的一个 JavaScript 对象映射,React 在做页面操作时,实际上不是间接操作 DOM,而是操作虚构 DOM,也就是操作一般的 JavaScript 对象,这就使得 SSR 成为了可能。在服务器,我能够操作 JavaScript 对象,判断环境是服务器环境,咱们把虚构 DOM 映射成字符串输入;在客户端,我也能够操作 JavaScript 对象,判断环境是客户端环境,我就间接将虚构 DOM 映射成实在 DOM,实现页面挂载。

SSR 框架图剖析

能够看到,这里波及两次路由:

服务器端路由:服务器端要依据申请的地址,判断要展现什么样的页面了。即在服务器端须要通过申请门路,找到路由组件

客户端路由(前端路由):当客户端接管到 JavaScript 文件后,要依据以后的门路,在浏览器上再判断以后要展现的组件,从新进行一次客户端渲染。即在客户端需通过浏览器中的网址,找到路由组件。

对于一个 React 利用来说,路由个别是整个程序的执行入口。在 SSR 中,服务器端的路由和客户端的路由不一样,也就意味着服务器端的入口代码和客户端的入口代码是不同的。

React 代码是要通过 Webpack 打包之后能力运行的,所以 3,10 步运行的代码,实际上是源代码打包过后生成的代码。所以,针对代码运行环境的不同,要进行有区别的 Webpack 打包。

服务器端路由 vs 客户端路由

实现 React 的 SSR 架构,咱们须要让雷同的 React 代码在客户端和服务器端各执行一次。大家留神,这里说的雷同的 React 代码,指的是咱们写的各种组件代码,所以在同构中,只有组件的代码是能够专用的,而路由这样的代码是没有方法专用的。

客户端路由:

// BrowserRouter 会主动从浏览器地址中,匹配对应的路由组件显示进去。

const App = () => {
  return (<Provider store={store}>
      <BrowserRouter>
        <div>
          <Route path='/' component={Home}>
          </div>
      </BrowserRouter>
    </Provider>
  )
}

ReactDom.render(<App/>, document.querySelector('#root'))

服务器端路由

const App = () => {
  return 
    <Provider store={store}>  
      <StaticRouter location={req.path} context={context}>
        <div>
          <Route path='/' component={Home}>
        </div>
      </StaticRouter>
    </Provider>
}

Return ReactDom.renderToString(<App/>)

服务器端路由代码绝对要简单一点,须要你把 location(以后申请门路)传递给 StaticRouter 组件,这样 StaticRouter 能力依据路径分析出以后所须要的组件是谁。(PS:StaticRouter 是 React-Router 针对服务器端渲染专门提供的一个路由组件。)

通过 BrowserRouter 咱们可能匹配到浏览器行将显示的路由组件,对浏览器来说,咱们须要把组件转化成 DOM,所以须要咱们应用 ReactDom.render 办法来进行 DOM 的挂载。而 StaticRouter 可能在服务器端匹配到将要显示的组件,对服务器端来说,咱们要把组件转化成字符串,这时咱们只须要调用 ReactDom 提供的 renderToString 办法,就能够失去 App 组件对应的 HTML 字符串。

 

2. 客户端渲染(CSR)

在当今 SPA 框架,Vue,React,Angular 大行天下的时候,前后端拆散开发异样可见。客户端渲染简略了解就是浏览器发送页面申请(第一次申请),服务器返回的是一个模板页面,浏览器从上至下解析过程中须要发送 ajax 申请获取数据(第二次申请),最初再调用模板引擎(art-template 等)渲染 HTML 构造,并把渲染后的后果增加到页面指定容器中,同时,JavaScript 代码会实现页面交互事件的绑定。

毛病:1. 首先要加载 HTML 文件,之后要下载页面所需的 JavaScript 文件,而后 JavaScript 文件渲染生成页面。在这个渲染过程中至多波及到两个 HTTP 申请周期。2. 因为目前大多数搜索引擎次要辨认的内容还是 HTML,对 JavaScript 文件内容的辨认都还比拟弱。CSR 我的项目的 SEO 能力极弱

客户端渲染因为数据是异步获取,所以在展现残缺页面的过程中起码发动两次申请,数据是动静的增加到页面中,因而,十分不利于 SEO,便于前后端拆散开发。现如今前端采纳 Vue 等框架开发十分多见,因而为了解决纯客户端渲染面临的问题,很多相似 Vue 中应用 SSR 和前后端同构的思维也十分常见。

具体流程图如下:

判断形式:查看网页源代码即可,如果是 ssr 形式,则能够间接看到数据。

3. 同构

当初咱们晓得浏览器显示页面:模板,内容(这俩能够认为是展现内容)和交互。显然 SSR 的交互还是须要 js 文件来执行

同构这个概念存在于 Vue,React 这些新型的前端框架中,同构实际上是客户端渲染和服务器端渲染的一个整合。咱们把页面的展现内容和交互写在一起,让代码执行两次。在服务器端执行一次,用于实现服务器端渲染,在客户端再执行一次,用于接管页面交互。

待更新

服务器端代码和客户端代码的打包差别
SSR 中异步数据的获取 + Redux 的应用

参考

Webpack 官方网站
What is React Server Side Rendering and should I use it?
StaticRouter
The Pain and the Joy of creating isomorphic apps in ReactJS
React 中同构(SSR)原理脉络梳理

退出移动版