React之服务端渲染
一、是什么
在SSR中 (opens new window),我们了解到Server-Side Rendering ,简称SSR,意为服务端渲染
指由服务侧完成页面的 HTML 结构拼接的页面处理技术,发送到浏览器,然后为其绑定状态与事件,成为完全可交互页面的过程

其解决的问题主要有两个:
- SEO,由于搜索引擎爬虫抓取工具可以直接查看完全渲染的页面
- 加速首屏加载,解决首屏白屏问题
二、如何做
在react中,实现SSR主要有两种形式:
- 手动搭建一个 SSR 框架
- 使用成熟的SSR 框架,如 Next.JS
这里主要以手动搭建一个SSR框架进行实现
首先通过express启动一个app.js文件,用于监听3000端口的请求,当请求根目录时,返回HTML,如下:
const express = require('express')
const app = express()
app.get('/', (req,res) => res.send(`
<html><head><title>ssr demo</title></head><body>Hello world</body>
</html>
`))app.listen(3000, () => console.log('Exampleapp listening on port 3000!'))
然后再服务器中编写react代码,在app.js中进行应引用
import React from 'react'const Home = () =>{return <div>home</div>}export default Home
为了让服务器能够识别JSX,这里需要使用webpakc对项目进行打包转换,创建一个配置文件webpack.server.js并进行相关配置,如下:
const path = require('path') //node的path模块
const nodeExternals = require('webpack-node-externals')module.exports = {target:'node',mode:'development', //开发模式entry:'./app.js', //入口output: { //打包出口filename:'bundle.js', //打包后的文件名path:path.resolve(__dirname,'build') //存放到根目录的build文件夹},externals: [nodeExternals()], //保持node中require的引用方式module: {rules: [{ //打包规则test: /\.js?$/, //对所有js文件进行打包loader:'babel-loader', //使用babel-loader进行打包exclude: /node_modules/,//不打包node_modules中的js文件options: {presets: ['react','stage-0',['env', { //loader时额外的打包规则,对react,JSX,ES6进行转换targets: {browsers: ['last 2versions'] //对主流浏览器最近两个版本进行兼容}}]]}}]}
}
接着借助react-dom提供了服务端渲染的 renderToString方法,负责把React组件解析成html
import express from 'express'
import React from 'react'//引入React以支持JSX的语法
import { renderToString } from 'react-dom/server'//引入renderToString方法
import Home from'./src/containers/Home'const app= express()
const content = renderToString(<Home/>)
app.get('/',(req,res) => res.send(`
<html><head><title>ssr demo</title></head><body>${content}</body>
</html>
`))app.listen(3001, () => console.log('Exampleapp listening on port 3001!'))
上面的过程中,已经能够成功将组件渲染到了页面上
但是像一些事件处理的方法,是无法在服务端完成,因此需要将组件代码在浏览器中再执行一遍,这种服务器端和客户端共用一套代码的方式就称之为同构
重构通俗讲就是一套React代码在服务器上运行一遍,到达浏览器又运行一遍:
- 服务端渲染完成页面结构
- 浏览器端渲染完成事件绑定
浏览器实现事件绑定的方式为让浏览器去拉取JS文件执行,让JS代码来控制,因此需要引入script标签
通过script标签为页面引入客户端执行的react代码,并通过express的static中间件为js文件配置路由,修改如下:
import express from 'express'
import React from 'react'//引入React以支持JSX的语法
import { renderToString } from'react-dom/server'//引入renderToString方法
import Home from './src/containers/Home'const app = express()
app.use(express.static('public'));
//使用express提供的static中间件,中间件会将所有静态文件的路由指向public文件夹const content = renderToString(<Home/>)app.get('/',(req,res)=>res.send(`
<html><head><title>ssr demo</title></head><body>${content}<script src="/index.js"></script></body>
</html>
`))app.listen(3001, () =>console.log('Example app listening on port 3001!'))
然后再客户端执行以下react代码,新建webpack.client.js作为客户端React代码的webpack配置文件如下:
const path = require('path') //node的path模块module.exports = {mode:'development', //开发模式entry:'./src/client/index.js', //入口output: { //打包出口filename:'index.js', //打包后的文件名path:path.resolve(__dirname,'public') //存放到根目录的build文件夹},module: {rules: [{ //打包规则test: /\.js?$/, //对所有js文件进行打包loader:'babel-loader', //使用babel-loader进行打包exclude: /node_modules/, //不打包node_modules中的js文件options: {presets: ['react','stage-0',['env', { //loader时额外的打包规则,这里对react,JSX进行转换targets: {browsers: ['last 2versions'] //对主流浏览器最近两个版本进行兼容}}]]}}]}
}
这种方法就能够简单实现首页的react服务端渲染,过程对应如下图:

在做完初始渲染的时候,一个应用会存在路由的情况,配置信息如下:
import React from 'react' //引入React以支持JSX
import { Route } from 'react-router-dom' //引入路由
import Home from './containers/Home' //引入Home组件export default (<div><Route path="/" exact component={Home}></Route></div>
)
然后可以通过index.js引用路由信息,如下:
import React from 'react'
import ReactDom from 'react-dom'
import { BrowserRouter } from'react-router-dom'
import Router from'../Routers'const App= () => {return (<BrowserRouter>{Router}</BrowserRouter>)
}ReactDom.hydrate(<App/>, document.getElementById('root'))
这时候控制台会存在报错信息,原因在于每个Route组件外面包裹着一层div,但服务端返回的代码中并没有这个div
解决方法只需要将路由信息在服务端执行一遍,使用使用StaticRouter来替代BrowserRouter,通过context进行参数传递
import express from 'express'
import React from 'react'//引入React以支持JSX的语法
import { renderToString } from 'react-dom/server'//引入renderToString方法
import { StaticRouter } from 'react-router-dom'
import Router from '../Routers'const app = express()
app.use(express.static('public'));
//使用express提供的static中间件,中间件会将所有静态文件的路由指向public文件夹app.get('/',(req,res)=>{const content = renderToString((//传入当前path//context为必填参数,用于服务端渲染参数传递<StaticRouter location={req.path} context={{}}>{Router}</StaticRouter>))res.send(`<html><head><title>ssr demo</title></head><body><div id="root">${content}</div><script src="/index.js"></script></body></html>`)
})app.listen(3001, () => console.log('Exampleapp listening on port 3001!'))
这样也就完成了路由的服务端渲染
三、原理
整体react服务端渲染原理并不复杂,具体如下:
node server 接收客户端请求,得到当前的请求url 路径,然后在已有的路由表内查找到对应的组件,拿到需要请求的数据,将数据作为 props、context或者store 形式传入组件
然后基于 react 内置的服务端渲染方法 renderToString()把组件渲染为 html字符串在把最终的 html进行输出前需要将数据注入到浏览器端
浏览器开始进行渲染和节点对比,然后执行完成组件内事件绑定和一些交互,浏览器重用了服务端输出的 html 节点,整个流程结束
相关文章:
React之服务端渲染
一、是什么 在SSR中 (opens new window),我们了解到Server-Side Rendering ,简称SSR,意为服务端渲染 指由服务侧完成页面的 HTML 结构拼接的页面处理技术,发送到浏览器,然后为其绑定状态与事件,成为完全可…...
jetson nano刷机更新Jetpack
只是记录个人在使用英伟达jetson Nano的经历,由于头一次尝试,所以特此记录需要的问题和经验。 一,英伟达刷机教程(jetson nano 版本) 本次我是直接刷机到TF卡,然后TF卡作为启动盘进行启动,我看网上有带EMMC版本的,好像可以直接把系统镜像安装到EMMC里面。但是有个问题…...
Android官方ShapeableImageView描边/圆形/圆角图,xml布局实现
Android官方ShapeableImageView描边/圆形/圆角图,xml布局实现 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:app"http://schemas.android.…...
ubuntu扩大运行内存, 防止编译卡死
首先查看交换分区大小 grep SwapTotal /proc/meminfo 1、关闭交换空间 sudo swapoff -a 2、扩充交换空间大小,count64就是64G 1G x 64 sudo dd if/dev/zero of/swapfile bs1G count64 3、设置权限 sudo chmod 600 /swapfile 4、指定交换空间对应的设备文件 …...
Kafka集群修改单个Topic数据保存周期
在大数据部门经常使用Kafka集群,有的时候大数据部门可能在Kafka中的Topic数据保存时间不需要很长,一旦被消费后就不需要一直保留。默认Topic存储时间为7day,个别的Topic或者某台Kafka集群需要修改Topic数据保存的一个周期,调整为3…...
selenium模拟登录无反应
在使用自动化工具selenium时对某些网站登录界面send_keys输入账号密码,运行时却没有自己想要的结果出现,这是因为你碰到前端二般的开发人员,他们用的是HTML嵌套,这对后端人员造成了一些麻烦,废话不多说,直接…...
指针变量未分配空间或者初始化为空指针使用问题
提示:关于指针 文章目录 前言一、指针的使用总结 前言 在看c书籍的时候,看到浅复制和深复制时,说到成员为指针的时候,会出异常。但是其实没有更多的感想,但是联想到上次考试指针没分配空间导致程序异常的情况…...
力扣第763题 划分字母区间 c++ 哈希 + 双指针 + 小小贪心
题目 763. 划分字母区间 中等 相关标签 贪心 哈希表 双指针 字符串 给你一个字符串 s 。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。 注意,划分结果需要满足:将所有划分结果按顺序连接,得…...
js 代码中的 “use strict“; 是什么意思 ?
use strict 是一种 ECMAscript5 添加的(严格)运行模式,这种模式使得 Javascript 在更严格的条件下运行。 设立"严格模式"的目的,主要有以下几个: 消除 Javascript 语法的一些不合理、不严谨之处,…...
用于读取验证码的 OCR 模型
介绍 此示例演示了使用功能 API 构建的简单 OCR 模型。除了结合 CNN 和 RNN 之外,它还说明了如何实例化新层并将其用作“端点层”来实现 CTC 损失。 设置 import os import numpy as np import matplotlib.pyplot as pltfrom pathlib import Path from collections import Co…...
Uniapp 跳转回上一页面并刷新页面数据
比如我从A页面跳转到B页面 然后再从B页面返回到A页面 顺带刷新一下A页面数据 let pages getCurrentPages(); // 当前页面 //获取当前页面栈let beforePage pages[pages.length - 3]; // //获取上一个页面实例对象beforePage.$vm.reloadList(); //调用它方法然后跳转…...
DeOldify 接口化改造 集成 Flask
类似的图片修复项目 GFPGAN 的改造见我另一篇文 https://blog.csdn.net/weixin_43074462/article/details/132497146 DeOldify 是一款开源软件,用于给黑白照片或视频上色,效果还不错。 安装部署教程请参考别的文章,本文基于你给项目跑通&…...
Vue 3响应式对象: ref和reactive
目录 什么是响应式对象? Ref Reactive Ref vs Reactive 适用场景: 访问方式: 引用传递: 性能开销: 响应式对象优点 响应式对象缺点 总结 Vue 3作为一种流行的JavaScript框架,提供了响应式编程的…...
Unity3D 如何用unity引擎然后用c#语言搭建自己的服务器
Unity3D是一款强大的游戏开发引擎,可以用于创建各种类型的游戏。在游戏开发过程中,经常需要与服务器进行通信来实现一些功能,比如保存和加载游戏数据、实现多人游戏等。本文将介绍如何使用Unity引擎和C#语言搭建自己的服务器,并给…...
带有 Vagrant 和 Virtualbox 的 Elasticsearch 集群
模拟分布式存储和计算环境的一种简单方法是使用 Virtualbox 作为 VM(“虚拟机”)的提供者,使用 Vagrant 作为前端脚本引擎来配置、启动和停止这些 VM。这篇文章的目标是构建一个集群虚拟设备,提供 Elasticsearch 作为可由主机使用…...
Cross Site Scripting (XSS)
攻击者会给网站发送可疑的脚本,可以获取浏览器保存的网站cookie, session tokens, 或者其他敏感的信息,甚至可以重写HTML页面的内容。 背景 XSS漏洞有不同类型,最开始发现的是存储型XSS和反射型XSS,2005,Am…...
VDA到Excel方案介绍之自定义邮件接收主题
VDA标准是德国汽车工业协会(Verband der Automobilindustrie,简称VDA)制定的一系列汽车行业标准。这些标准包括了汽车生产、质量管理、供应链管理、环境保护、安全性能等方面的规范和指南。VDA标准通常被德国和国际上的汽车制造商采用&#x…...
【opencv】【CPU】windows10下opencv4.8.0-cuda C++版本源码编译教程
【opencv】【CPU】windows10下opencv4.8.0-cuda C版本源码编译教程 提示:博主取舍了很多大佬的博文并亲测有效,分享笔记邀大家共同学习讨论 文章目录 【opencv】【CPU】windows10下opencv4.8.0-cuda C版本源码编译教程前言准备工具cmakeopencv4.8.0opencv_contrib CMake编译VS2…...
多分类loss学习记录
这里简单的记录在人脸识别/声纹识别中常用的分类loss。详细原理可以参考其他博客。 扩展资料1 扩展资料2 L-softmax A-softmax AM-softmax L-softmax :基于softmax加入了margin, Wx 改写为||w||||x||cos(角度),将角度变为了m角度 A-softmax &…...
Linux创建逻辑卷并扩容(超详细)
目录 编辑 一、概念解析 1、LV逻辑卷 2、PV物理卷 3、VG卷组 二、扩容前准备 三、创建逻辑卷并扩容 1、打开虚拟机 2、进入root用户 3、查看新加入的硬盘 4、创建主分区 5、创建物理卷 6、打包为一个卷组 7、创建逻辑卷 8、格式化逻辑卷 9、挂载逻辑卷--开机自…...
纯血鸿蒙彻底告别安卓依赖:HarmonyOS 7.0 即将正式发布,国产操作系统迎来真正转折点
OpenHarmony 7.0 Beta1已经悄然上线GitCode,开发者体验官招募也同步启动。多数人还在讨论鸿蒙又更新了版本,但很少有人注意到这次更新的核心变化:纯血鸿蒙终于移除了对Android APK兼容层的依赖。这仅仅是一次常规版本迭代吗?还是国…...
互联网大厂 Java 求职面试:从微服务到 AI 的探索之旅
互联网大厂 Java 求职面试:从微服务到 AI 的探索之旅 面试官:燕双非,欢迎你来到我们的面试。今天我们主要聊聊在电商场景下 Java 的微服务架构,你准备好了吗? 燕双非:准备好了,我觉得电商系统就…...
工业视觉开发的基石:GenICam 简介
在工业自动化和机器视觉领域,“碎片化”曾是开发者面临的最大痛点。不同品牌的相机使用不同的通信协议、参数定义和 SDK。为了获取一张图像或调节曝光时间,开发者往往需要学习多个厂商的驱动接口。而 GenICam (Generic Interface for Cameras) 标准的出现…...
Lindy流程自动化效果衰减真相:3年追踪数据显示,未做持续治理的企业6个月后效率回落至基线112%
更多请点击: https://codechina.net 第一章:Lindy流程自动化效果衰减真相:3年追踪数据显示,未做持续治理的企业6个月后效率回落至基线112% Lindy效应在流程自动化领域呈现显著反向特征:系统上线初期的效率跃升并非稳态…...
【Elasticsearch从入门到精通】第15篇:Elasticsearch删除与更新API——精确操作与脚本更新
上一篇【第14篇】Elasticsearch文档检索API——GET、MGet与字段选择 下一篇【第16篇】Elasticsearch批量操作API——Bulk、Reindex与跨集群索引 摘要 数据的删除和更新是Elasticsearch文档操作中不可或缺的环节。本文全面讲解了Elasticsearch删除与更新API的使用方法ÿ…...
Linux驱动开发:/proc接口创建与安全实现指南
1. 项目概述:为什么我们需要关注/proc接口?在Linux驱动开发的世界里,与用户空间进行数据交换是家常便饭。你写了一个驱动,控制着某个硬件,但总得有个“窗口”让系统管理员或者上层应用能看看它运行得怎么样,…...
AI 调研平台,以智能技术重构全域调研数字化体系
在各行各业的业务研判、市场分析、工作调研场景中,传统调研模式长期依赖人工采集、手动整理、经验分析,存在明显的技术与效率短板。人工调研数据来源零散、数据清洗繁琐、分析维度单一,不仅耗费大量人力时间,还容易出现数据遗漏、…...
Hackbar收费了怎么办?手把手教你配置Tampermonkey脚本实现类似功能(附常用脚本分享)
Hackbar收费后的完美替代方案:Tampermonkey脚本实战指南 当Hackbar从免费转向收费模式时,许多安全研究人员和开发者都感到措手不及。这款曾经被誉为"渗透测试瑞士军刀"的浏览器插件突然变成了付费墙后的工具,让不少用户开始寻找替…...
贴吧Lite:如何用轻量级客户端获得极致贴吧体验
贴吧Lite:如何用轻量级客户端获得极致贴吧体验 【免费下载链接】TiebaLite 贴吧 Lite 项目地址: https://gitcode.com/gh_mirrors/tieb/TiebaLite 还在为官方贴吧应用的臃肿设计和无处不在的广告烦恼吗?贴吧Lite作为一款革命性的第三方贴吧客户端…...
3个关键策略:安全使用ViVeTool-GUI控制Windows隐藏功能
3个关键策略:安全使用ViVeTool-GUI控制Windows隐藏功能 【免费下载链接】ViVeTool-GUI Windows Feature Control GUI based on ViVe / ViVeTool 项目地址: https://gitcode.com/gh_mirrors/vi/ViVeTool-GUI ViVeTool-GUI是一款基于ViVe/ViVeTool的Windows功能…...
