react ssr原理

ssr

什麼是ssr:server side render,服務端渲染php

不一樣於jsp,php等傳統服務端渲染(這種狀況下,先後端代碼是分開的,寫了兩份)html

目前的ssr是基於react vue等前端框架的同構渲染(即一份代碼,同時運行在server和client端),開發人員只關注業務實現便可前端

ssr的優缺點就不細說了,無非seo,首屏更快,學習成本變高,加大服務端資源開銷等vue

目前咱們項目都逐步採用ssr方案,基於nextjs重構,做爲開發人員,對原理比較好奇,研究一下node

基本流程

大體的流程以下圖react

圖片描述

打包階段會將業務代碼打包兩次,一份部署在服務端,一份用於客戶端(可傳到cdn)git

而後啓動服務,基於用戶請求的路由決定render哪一個頁面,主要用到renderToStringapi將page組件轉化爲html標記github

最簡單的狀況,將html標記直接返回客戶端,渲染一個靜態頁面後端

但實際業務中,通常在服務端須要獲取數據,根據數據來生成html,這種狀況下,當在客戶端從新render時,如何保證數據一致呢,解決辦法是將服務端獲取到的數據以字符串的形式返回給客戶端,客戶端渲染的時候直接以該數據進行渲染,保證數據的一致性,進而保證了ui的一致性api

當在客戶端運行時,主要用hydrateapi將html標記與js代碼從新結合,以後就與服務端徹底不要緊了,能夠當spa的狀況處理

demo

基於這個流程,簡單實現一個demo

準備

服務端

  • 首先須要node服務,該demo採用koa
  • node端實現render邏輯,引入組件,獲取數據,將數據傳入page組件,並利用renderToString生成標記
  • 返回標記與數據給客戶端

客戶端

  • 獲取服務端數據
  • 將數據傳入page組件並利用hydrate render頁面

主要代碼實現:

server端

// render頁面
async function render(Element) {
  // 獲取組件初始props,能夠在該方法內獲取數據
  const props = await Element.getInitProps()

  const html = renderToString(<Element {...props} />)
  const __SSR_DATA__ = {
    props
  }

  return {
    html,
    __SSR_DATA__
  }
}

router.get('/demo', async ctx => {
  // 將生成的標記和屬性都轉爲文本傳給客戶端
  const { html, __SSR_DATA__ } = await render(Demo)
  ctx.body = `<!DOCTYPE html>
  <html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>ssr</title>
  </head>
  <body>
    <script>
      window.__SSR_DATA__ = ${JSON.stringify(__SSR_DATA__)}
    </script>
    <div id="root">${html}</div>
    <script src="http://localhost:9090/index.js"></script>
  </body>
  </html>`
})

客戶端

import { hydrate } from 'react-dom';
import Demo from './demo';

// 服務端將props數據掛載到window上,客戶端從新渲染時直接傳入該屬性
const { props } = window.__SSR_DATA__

// hydrate會根據html中已有的標記進行對比,決定是否要從新渲染dom
hydrate(
  <Demo {...props} />,
  document.getElementById('root'),
);

倉庫地址

ssr

nextjs

目前react ssr主要是用nextjs

nextjs實現原理與上面一致,增長了路由,緩存,打包,錯誤處理,頁面加載等一系列功能

生產中,除非很簡單,或者只爲了首屏,不考慮同構,能夠本身實現,正常狀況,直接使用nextjs便可

後續會記錄一下next源碼分析

待續...

相關文章
相關標籤/搜索