日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

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

新聞中心

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

本文轉載自微信公眾號「JS每日一題」,作者灰灰。轉載本文請聯(lián)系JS每日一題公眾號。

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

一、是什么

在SSR中,我們了解到Server-Side Rendering ,簡稱SSR,意為服務端渲染

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

其解決的問題主要有兩個:

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

二、如何做

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

  • 手動搭建一個 SSR 框架
  • 使用成熟的SSR 框架,如 Next.JS

這里主要以手動搭建一個SSR框架進行實現(xiàn)

首先通過express啟動一個app.js文件,用于監(jiān)聽3000端口的請求,當請求根目錄時,返回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!'))

然后再服務器中編寫react代碼,在app.js中進行應引用

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

為了讓服務器能夠識別JSX,這里需要使用webpakc對項目進行打包轉換,創(chuàng)建一個配置文件webpack.server.js并進行相關配置,如下:

 
 
 
 
  1. const path = require('path')    //node的path模塊
  2. const nodeExternals = require('webpack-node-externals')
  3. module.exports = {
  4.     target:'node',
  5.     mode:'development',           //開發(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?$/,       //對所有js文件進行打包
  15.            loader:'babel-loader',  //使用babel-loader進行打包
  16.            exclude: /node_modules/,//不打包node_modules中的js文件
  17.            options: {
  18.                presets: ['react','stage-0',['env', { 
  19.                                   //loader時額外的打包規(guī)則,對react,JSX,ES6進行轉換
  20.                     targets: {
  21.                         browsers: ['last 2versions']   //對主流瀏覽器最近兩個版本進行兼容
  22.                     }
  23.                }]]
  24.            }
  25.        }]
  26.     }
  27. }

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

 
 
 
 
  1. import express from 'express'
  2. import React from 'react'//引入React以支持JSX的語法
  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!'))

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

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

重構通俗講就是一套React代碼在服務器上運行一遍,到達瀏覽器又運行一遍:

  • 服務端渲染完成頁面結構
  • 瀏覽器端渲染完成事件綁定

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

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

 
 
 
 
  1. import express from 'express'
  2. import React from 'react'//引入React以支持JSX的語法
  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中間件,中間件會將所有靜態(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',                         //開發(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?$/,                    //對所有js文件進行打包
  12.            loader:'babel-loader',               //使用babel-loader進行打包
  13.            exclude: /node_modules/,             //不打包node_modules中的js文件
  14.            options: {
  15.                presets: ['react','stage-0',['env', {     
  16.                     //loader時額外的打包規(guī)則,這里對react,JSX進行轉換
  17.                     targets: {
  18.                         browsers: ['last 2versions']   //對主流瀏覽器最近兩個版本進行兼容
  19.                     }
  20.                }]]
  21.            }
  22.        }]
  23.     }
  24. }

這種方法就能夠簡單實現(xiàn)首頁的react服務端渲染,過程對應如下圖:

在做完初始渲染的時候,一個應用會存在路由的情況,配置信息如下:

 
 
 
 
  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.     
  • )
  • 然后可以通過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'))

    這時候控制臺會存在報錯信息,原因在于每個Route組件外面包裹著一層div,但服務端返回的代碼中并沒有這個div

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

     
     
     
     
    1. import express from 'express'
    2. import React from 'react'//引入React以支持JSX的語法
    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中間件,中間件會將所有靜態(tài)文件的路由指向public文件夾
    10. app.get('/',(req,res)=>{
    11.     const content  = renderToString((
    12.         //傳入當前path
    13.         //context為必填參數(shù),用于服務端渲染參數(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!'))
  • 這樣也就完成了路由的服務端渲染

    三、原理

    整體react服務端渲染原理并不復雜,具體如下:

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

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

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

    參考文獻

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

    網(wǎng)頁標題:面試官:說說React服務端渲染怎么做?原理是什么?
    文章起源:http://www.dlmjj.cn/article/dhhsego.html