日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
面試官:說(shuō)說(shuō)React服務(wù)端渲染怎么做?原理是什么?

本文轉(zhuǎn)載自微信公眾號(hào)「JS每日一題」,作者灰灰。轉(zhuǎn)載本文請(qǐng)聯(lián)系JS每日一題公眾號(hào)。

在龍鳳等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強(qiáng)發(fā)展的系統(tǒng)性、市場(chǎng)前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供成都做網(wǎng)站、成都網(wǎng)站制作、成都外貿(mào)網(wǎng)站建設(shè) 網(wǎng)站設(shè)計(jì)制作按需策劃,公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),成都品牌網(wǎng)站建設(shè),成都全網(wǎng)營(yíng)銷推廣,成都外貿(mào)網(wǎng)站建設(shè)公司,龍鳳網(wǎng)站建設(shè)費(fèi)用合理。

一、是什么

在SSR中,我們了解到Server-Side Rendering ,簡(jiǎn)稱SSR,意為服務(wù)端渲染

指由服務(wù)側(cè)完成頁(yè)面的 HTML 結(jié)構(gòu)拼接的頁(yè)面處理技術(shù),發(fā)送到瀏覽器,然后為其綁定狀態(tài)與事件,成為完全可交互頁(yè)面的過(guò)程

其解決的問(wèn)題主要有兩個(gè):

  • SEO,由于搜索引擎爬蟲抓取工具可以直接查看完全渲染的頁(yè)面
  • 加速首屏加載,解決首屏白屏問(wèn)題

二、如何做

在react中,實(shí)現(xiàn)SSR主要有兩種形式:

  • 手動(dòng)搭建一個(gè) SSR 框架
  • 使用成熟的SSR 框架,如 Next.JS

這里主要以手動(dòng)搭建一個(gè)SSR框架進(jìn)行實(shí)現(xiàn)

首先通過(guò)express啟動(dòng)一個(gè)app.js文件,用于監(jiān)聽(tīng)3000端口的請(qǐng)求,當(dāng)請(qǐng)求根目錄時(shí),返回HTML,如下:

 
 
 
 
  1. const express = require('express')
  2. const app = express()
  3. app.get('/', (req,res) => res.send(`
  4.    
  5.        SSR demo
  6.    
  7.    
  8.        Hello world
  9.    
  10. `))
  11. app.listen(3000, () => console.log('Exampleapp listening on port 3000!'))

然后再服務(wù)器中編寫react代碼,在app.js中進(jìn)行應(yīng)引用

 
 
 
 
  1. import React from 'react'
  2. const Home = () =>{
  3.     return 
    home
  4. }
  5. export default Home

為了讓服務(wù)器能夠識(shí)別JSX,這里需要使用webpakc對(duì)項(xiàng)目進(jìn)行打包轉(zhuǎn)換,創(chuàng)建一個(gè)配置文件webpack.server.js并進(jìn)行相關(guān)配置,如下:

 
 
 
 
  1. const path = require('path')    //node的path模塊
  2. const nodeExternals = require('webpack-node-externals')
  3. module.exports = {
  4.     target:'node',
  5.     mode:'development',           //開(kāi)發(fā)模式
  6.     entry:'./app.js',             //入口
  7.     output: {                     //打包出口
  8.         filename:'bundle.js',     //打包后的文件名
  9.         path:path.resolve(__dirname,'build')    //存放到根目錄的build文件夾
  10.     },
  11.     externals: [nodeExternals()],  //保持node中require的引用方式
  12.     module: {
  13.         rules: [{                  //打包規(guī)則
  14.            test:   /\.js?$/,       //對(duì)所有js文件進(jìn)行打包
  15.            loader:'babel-loader',  //使用babel-loader進(jìn)行打包
  16.            exclude: /node_modules/,//不打包node_modules中的js文件
  17.            options: {
  18.                presets: ['react','stage-0',['env', { 
  19.                                   //loader時(shí)額外的打包規(guī)則,對(duì)react,JSX,ES6進(jìn)行轉(zhuǎn)換
  20.                     targets: {
  21.                         browsers: ['last 2versions']   //對(duì)主流瀏覽器最近兩個(gè)版本進(jìn)行兼容
  22.                     }
  23.                }]]
  24.            }
  25.        }]
  26.     }
  27. }

接著借助react-dom提供了服務(wù)端渲染的 renderToString方法,負(fù)責(zé)把React組件解析成html

 
 
 
 
  1. import express from 'express'
  2. import React from 'react'//引入React以支持JSX的語(yǔ)法
  3. import { renderToString } from 'react-dom/server'//引入renderToString方法
  4. import Home from'./src/containers/Home'
  5. const app= express()
  6. const content = renderToString()
  7. app.get('/',(req,res) => res.send(`
  8.    
  9.        SSR demo
  10.    
  11.    
  12.         ${content}
  13.    
  14. `))
  15. app.listen(3001, () => console.log('Exampleapp listening on port 3001!'))

上面的過(guò)程中,已經(jīng)能夠成功將組件渲染到了頁(yè)面上

但是像一些事件處理的方法,是無(wú)法在服務(wù)端完成,因此需要將組件代碼在瀏覽器中再執(zhí)行一遍,這種服務(wù)器端和客戶端共用一套代碼的方式就稱之為「同構(gòu)」

重構(gòu)通俗講就是一套R(shí)eact代碼在服務(wù)器上運(yùn)行一遍,到達(dá)瀏覽器又運(yùn)行一遍:

  • 服務(wù)端渲染完成頁(yè)面結(jié)構(gòu)
  • 瀏覽器端渲染完成事件綁定

瀏覽器實(shí)現(xiàn)事件綁定的方式為讓瀏覽器去拉取JS文件執(zhí)行,讓JS代碼來(lái)控制,因此需要引入script標(biāo)簽

通過(guò)script標(biāo)簽為頁(yè)面引入客戶端執(zhí)行的react代碼,并通過(guò)express的static中間件為js文件配置路由,修改如下:

 
 
 
 
  1. import express from 'express'
  2. import React from 'react'//引入React以支持JSX的語(yǔ)法
  3. import { renderToString } from'react-dom/server'//引入renderToString方法
  4. import Home from './src/containers/Home'
  5.  
  6. const app = express()
  7. app.use(express.static('public'));
  8. //使用express提供的static中間件,中間件會(huì)將所有靜態(tài)文件的路由指向public文件夾
  9.  const content = renderToString()
  10.  
  11. app.get('/',(req,res)=>res.send(`
  12.    
  13.        SSR demo
  14.    
  15.    
  16.         ${content}
  17.    
  18.    
  19. `))
  20.  app.listen(3001, () =>console.log('Example app listening on port 3001!'))

然后再客戶端執(zhí)行以下react代碼,新建webpack.client.js作為客戶端React代碼的webpack配置文件如下:

 
 
 
 
  1. const path = require('path')                    //node的path模塊
  2. module.exports = {
  3.     mode:'development',                         //開(kāi)發(fā)模式
  4.     entry:'./src/client/index.js',              //入口
  5.     output: {                                   //打包出口
  6.         filename:'index.js',                    //打包后的文件名
  7.         path:path.resolve(__dirname,'public')   //存放到根目錄的build文件夾
  8.     },
  9.     module: {
  10.         rules: [{                               //打包規(guī)則
  11.            test:   /\.js?$/,                    //對(duì)所有js文件進(jìn)行打包
  12.            loader:'babel-loader',               //使用babel-loader進(jìn)行打包
  13.            exclude: /node_modules/,             //不打包node_modules中的js文件
  14.            options: {
  15.                presets: ['react','stage-0',['env', {     
  16.                     //loader時(shí)額外的打包規(guī)則,這里對(duì)react,JSX進(jìn)行轉(zhuǎn)換
  17.                     targets: {
  18.                         browsers: ['last 2versions']   //對(duì)主流瀏覽器最近兩個(gè)版本進(jìn)行兼容
  19.                     }
  20.                }]]
  21.            }
  22.        }]
  23.     }
  24. }

這種方法就能夠簡(jiǎn)單實(shí)現(xiàn)首頁(yè)的react服務(wù)端渲染,過(guò)程對(duì)應(yīng)如下圖:

在做完初始渲染的時(shí)候,一個(gè)應(yīng)用會(huì)存在路由的情況,配置信息如下:

 
 
 
 
  1. import React from 'react'                   //引入React以支持JSX
  2. import { Route } from 'react-router-dom'    //引入路由
  3. import Home from './containers/Home'        //引入Home組件
  4. export default (
  5.     
  6.         
  7.     
  • )
  • 然后可以通過(guò)index.js引用路由信息,如下:

     
     
     
     
    1. import React from 'react'
    2. import ReactDom from 'react-dom'
    3. import { BrowserRouter } from'react-router-dom'
    4. import Router from'../Routers'
    5. const App= () => {
    6.     return (
    7.         
    8.            {Router}
    9.         
    10.     )
    11. }
    12. ReactDom.hydrate(, document.getElementById('root'))

    這時(shí)候控制臺(tái)會(huì)存在報(bào)錯(cuò)信息,原因在于每個(gè)Route組件外面包裹著一層div,但服務(wù)端返回的代碼中并沒(méi)有這個(gè)div

    解決方法只需要將路由信息在服務(wù)端執(zhí)行一遍,使用使用StaticRouter來(lái)替代BrowserRouter,通過(guò)context進(jìn)行參數(shù)傳遞

     
     
     
     
    1. import express from 'express'
    2. import React from 'react'//引入React以支持JSX的語(yǔ)法
    3. import { renderToString } from 'react-dom/server'//引入renderToString方法
    4. import { StaticRouter } from 'react-router-dom'
    5. import Router from '../Routers'
    6.  
    7. const app = express()
    8. app.use(express.static('public'));
    9. //使用express提供的static中間件,中間件會(huì)將所有靜態(tài)文件的路由指向public文件夾
    10. app.get('/',(req,res)=>{
    11.     const content  = renderToString((
    12.         //傳入當(dāng)前path
    13.         //context為必填參數(shù),用于服務(wù)端渲染參數(shù)傳遞
    14.         
    15.            {Router}
    16.         
    17.     ))
    18.     res.send(`
    19.    
    20.        
    21.            SSR demo
    22.        
    23.        
    24.        ${content}
  •        
  •        
  •    
  •     `)
  • })
  • app.listen(3001, () => console.log('Exampleapp listening on port 3001!'))
  • 這樣也就完成了路由的服務(wù)端渲染

    三、原理

    整體react服務(wù)端渲染原理并不復(fù)雜,具體如下:

    node server 接收客戶端請(qǐng)求,得到當(dāng)前的請(qǐng)求url 路徑,然后在已有的路由表內(nèi)查找到對(duì)應(yīng)的組件,拿到需要請(qǐng)求的數(shù)據(jù),將數(shù)據(jù)作為 props、context或者store 形式傳入組件

    然后基于 react 內(nèi)置的服務(wù)端渲染方法 renderToString()把組件渲染為 html字符串在把最終的 html進(jìn)行輸出前需要將數(shù)據(jù)注入到瀏覽器端

    瀏覽器開(kāi)始進(jìn)行渲染和節(jié)點(diǎn)對(duì)比,然后執(zhí)行完成組件內(nèi)事件綁定和一些交互,瀏覽器重用了服務(wù)端輸出的 html 節(jié)點(diǎn),整個(gè)流程結(jié)束

    參考文獻(xiàn)

    • https://zhuanlan.zhihu.com/p/52693113
    • https://segmentfault.com/a/1190000020417285
    • https://juejin.cn/post/6844904000387563533#heading-14

    當(dāng)前名稱:面試官:說(shuō)說(shuō)React服務(wù)端渲染怎么做?原理是什么?
    分享路徑:http://m.5511xx.com/article/dhhsego.html