百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

一文带你搞懂vue/react应用中实现ssr(服务端渲染)

suiw9 2024-11-17 01:42 29 浏览 0 评论

作者: 徐小夕

转发链接:https://mp.weixin.qq.com/s/1nQdWmzOTSGXLAtHUC4Nhg

前言

我们都知道, VueReact是构建客户端应用程序的框架。默认情况下,可以在浏览器中输出自定义组件,进行生成 DOM 和操作 DOM, 也就是我们常说的客户端渲染, 并且我们大部分主流的场景都是SPA(单页面)应用, 而随着 SPA尤其是 ReactVueAngular 为代表的前端框架的流行,越来越多的 WebApp 使用的是客户端渲染。


使用客户端渲染的优势在于节省后端资源局部刷新前后端分离等,但随着应用的日益复杂, 首屏渲染时间不断变长, 并且存在严重的SEO问题。

所以为了解决SPA应用遇到的这些问题, 我们必须考虑SSR:

服务端渲染(ssr),是指由服务器端完成页面的HTML 结构拼接,并且直接将拼接好的HTML发送到浏览器,然后为其绑定状态与事件,成为完全可交互页面的处理技术。

对于服务端渲染的页面,服务端可以直接将带数据的内容通过 HTML 文本的形式返回,搜索引擎爬虫可以轻易的获取页面内容,而对于客户端渲染的应用,客户端必须执行服务器返回的 Javascript 才能得到正确的网页内容。目前,除GoogleBing 支持 Javascript 外(也会有一些限制),其他的大部分搜索引擎都不支持 Javascript,也就无法获取正确的网页内容。而本文要讲的技术方案,正是为了解决SPA下的SSR技术困境.接下来我们看看常用的ssr技术实现方案.

摘要

ssr(服务端渲染)技术实现方案

接下来笔者将列举几个常用的基于vue/react的服务端渲染方案,如下:

  • 使用next.js/nuxt.js的服务端渲染方案
  • 使用node+vue-server-renderer实现vue项目的服务端渲染
  • 使用node+React renderToStaticMarkup实现react项目的服务端渲染
  • 传统网站通过模板引擎来实现ssr(比如ejs, jade, pug等)
  • 使用rendertron实现SPA项目的服务端渲染

以上是笔者之前实践过的方案, 最后一种方案笔者将在下面一节详细介绍, 因为next/nuxt是已有的服务端渲染解决方案,文档写的比较详细,这里笔者就不再做过多介绍了,这里我们简单介绍一下第二种和第三种方案.

1.使用node+vue-server-renderer实现vue项目的服务端渲染

首先vue-server-renderer依赖node的api,所以只能运行在node环境, 我们需要先安装它:

npm install vue vue-server-renderer --save

在node中使用,代码如下:

const Vue = require('vue')
const server = require('express')()
const renderer = require('vue-server-renderer').createRenderer()

server.get('*', (req, res) => {
  const app = new Vue({
    data: {
      url: req.url
    },
    template: `<div>趣谈前端:{{ url }}</div>`
  })

  renderer.renderToString(app, (err, html) => {
    if (err) {
      res.status(500).end('Internal Server Error')
      return
    }
    res.end(`
      <!DOCTYPE html>
      <html lang="en">
        <head><title>Hello</title></head>
        <body>${html}</body>
      </html>
    `)
  })
})

server.listen(8080)

当然实际情况比上面的案例要复杂很多, 我们可以专门写一个template.html,然后通过模板差值的方式导入后端数据,进而实现服务端渲染. 在使用这种方式的时候我们仍然要维护两套代码.

2.使用node+React renderToStaticMarkup实现react项目的服务端渲染

使用这种方案和vue的方案类似, 只不过这里我们用了react自带的api来实现ssr,简单的实现代码如下:

var express = require('express');
var app = express();
 
var React = require('react'),
    ReactDOMServer = require('react-dom/server');
 
var App = React.createFactory(require('./App'));
 
app.get('/', function(req, res) {
    var html = ReactDOMServer.renderToStaticMarkup(
        React.DOM.body(
            null,
            React.DOM.div({id: 'root',
                dangerouslySetInnerHTML: {
                    __html: ReactDOMServer.renderToStaticMarkup(App())
                }
            })
        )
    );
 
    res.end(html);
});
 
app.listen(80, function() {
    console.log('running on port ' + 80);
});

以上使用了renderToStaticMarkup, 我们都知道react-dom提供了两种服务端渲染函数,如下:

  1. renderToString:将 React Component 转化为 HTML 字符串,生成的 HTML 的 DOM 会带有额外属性:各个 DOM 会有data-react-id属性,第一个 DOM 会有data-checksum属性。
  2. renderToStaticMarkup:将 React Component 转化为 HTML 字符串,但是生成 HTML 的 DOM 不会有额外属性,从而节省 HTML 字符串的大小。

所以这里我们一般使用renderToStaticMarkup函数. 同理在实际业务场景中我们也会写2套代码来实现ssr.

使用谷歌rendertron实现服务端渲染

Google 推出的 Rendertron 使得 SPA 也能够被不支持执行 Javascript 的搜索引擎爬取渲染后的内容。其原理主要是通过使用 Headless Chrome 在内存中执行 Javascript,并在得到完整内容后,将内容返回给客户端。

我们通常会将 Rendertron 部署为一个独立的 HTTP 服务,然后为 Web 应用框架配置 Google 官方提供的中间件或者在反向代理上添加相应路由规则,使得能够在检测到搜索引擎爬虫的 UA 时,可以将请求代理给 Rendertron 服务。笔者总结了一下其基本实现原理图,方便大家理解:


Rendertron 提供了两个主要 API:

  • Render 用于渲染网站内容
  • Screenshot 用于将网站内容截图

在 SEO 场景下我们使用的是 Render 接口。

比如当客户端请求我们的网站时,我们服务端可以根据请求头 User Agent 发现是否包含了 Baiduspider/2.0 关键字,如果是, 那么可以认定为当前的客户端是一个百度爬虫此时可以将这个请求代理 Rendertron 服务的 /render/客户端请求地址 路由,让 Rendertron 帮助执行网页内的 Javascript,并将最终内容返回给搜索引擎爬虫。

使用Rendertron的好处在于我们可以不用考虑服务端渲染的部分,完全按照SPA的模式开发项目,也不用为了兼容服务端渲染而写多余的兼容代码.

具体实现

首先我们需要安装Rendertron, 可以在github中找到其安装和使用方法,在安装前最好先安装docker, 目前docker的最新版本以支持傻瓜式安装,所以安装启动都非常方便.

1.本地运行

在安装好docker之后, 我们先全局安装rendertron:

npm install -g rendertron

然后我们需要安装谷歌浏览器(作为合格的开发都应该有谷歌浏览器~),然后就可以用它的cli来启动服务了,我们只需要在命令行执行如下命令:

rendertron

之后控制台会打印本地服务启动的地址,比如localhost:3000 这个时候我们只需要在地址后面输入我们想渲染的网站即可:localhost:3000:render/你的网站地址, 如下图所示:

此时我们的rendertron服务已经搭建完成, 接下来我们可以在服务端来实现ssr了,代码如下:

const koa = require('koa');
const app = new koa();
app.use(async (ctx, next) => {
    ctx.type = "html";
    if(/Baiduspider\/2\.0/g.ctx.header['user-agent']) {
      // 是百度爬虫,则转发到rendertron服务中
      ctx.redirect(`http://localhost:3000/render/${ctx.url}`)
    }else {
        // 渲染正常的路由页面
    }

    await next();
    })

app.listen('80');

当然如果我们后端技术栈采用的是express, rendertron有专门的中间件可以使用, 不仅仅可以拦截百度的爬虫,具体用法如下:

const express = require('express');
const rendertron = require('rendertron-middleware');

const app = express();

app.use(rendertron.makeMiddleware({
  proxyUrl: 'http://your-rendertron-instance/render',
}));

// 正常的路由和页面渲染逻辑
app.use(...);
app.listen(81);

所以为了降低开发成本笔者建议可以采用rendertron的方案, 单独部署一套服务器用来实现ssr. 但是我们需要考虑当网站流量增加时的扩容问题,以及配置搭建反向代理或负载均衡等配套服务。

后期展望

后期笔者将会继续带大家探索大前端相关内容, 基本框架如下:

推荐Vue学习资料文章:

Vue+CSS3 实现图片滑块效果

教你Vue3 Compiler 优化细节,如何手写高性能渲染函数(上)

教你Vue3 Compiler 优化细节,如何手写高性能渲染函数(下)

vue实现一个6个输入框的验证码输入组件

一用惊人的Vue实践技巧「值得推荐」

Vue常见的面试知识点汇总(上)「附答案」

Vue常见的面试知识点汇总(下)「附答案」

Kbone原理详解与小程序技术选型

为什么我不再用Vue,改用React?

让Jenkins自动部署你的Vue项目「实践」

20个免费的设计资源 UI套件背景图标CSS框架

Deno将停止使用TypeScript,并公布五项具体理由

前端骨架屏都是如何生成的

Vue原来可以这样写开发效率杠杠的

用vue简单写一个音乐播放组件「附源码」

为什么Vue3.0不再使用defineProperty实现数据监听?

「干货」学会这些Vue小技巧,可以早点下班和女神约会

探索 Vue-Multiselect

细品30张脑图带你从零开始学Vue

Vue后台项目中遇到的技术难点以及解决方案

手把手教你Electron + Vue实战教程(五)

手把手教你Electron + Vue实战教程(四)

手把手教你Electron + Vue实战教程(三)

手把手教你Electron + Vue实战教程(二)

手把手教你Electron + Vue实战教程(一)

收集22种开源Vue模板和主题框架「干货」

如何写出优秀后台管理系统?11个经典模版拿去不谢「干货」

手把手教你实现一个Vue自定义指令懒加载

基于 Vue 和高德地图实现地图组件「实践」

一个由 Vue 作者尤雨溪开发的 web 开发工具—vite

是什么让我爱上了Vue.js

1.1万字深入细品Vue3.0源码响应式系统笔记「上」

1.1万字深入细品Vue3.0源码响应式系统笔记「下」

「实践」Vue 数据更新7 种情况汇总及延伸解决总结

尤大大细说Vue3 的诞生之路「译」

提高10倍打包速度工具Snowpack 2.0正式发布,再也不需要打包器

大厂Code Review总结Vue开发规范经验「值得学习」

Vue3 插件开发详解尝鲜版「值得收藏」

带你五步学会Vue SSR

记一次Vue3.0技术干货分享会

Vue 3.x 如何有惊无险地快速入门「进阶篇」

「干货」微信支付前后端流程整理(Vue+Node)

带你了解 vue-next(Vue 3.0)之 炉火纯青「实践」

「干货」Vue+高德地图实现页面点击绘制多边形及多边形切割拆分

「干货」Vue+Element前端导入导出Excel

「实践」Deno bytes 模块全解析

细品pdf.js实践解决含水印、电子签章问题「Vue篇」

基于vue + element的后台管理系统解决方案

Vue仿蘑菇街商城项目(vue+koa+mongodb)

基于 electron-vue 开发的音乐播放器「实践」

「实践」Vue项目中标配编辑器插件Vue-Quill-Editor

基于 Vue 技术栈的微前端方案实践

消息队列助你成为高薪 Node.js 工程师

Node.js 中的 stream 模块详解

「干货」Deno TCP Echo Server 是怎么运行的?

「干货」了不起的 Deno 实战教程

「干货」通俗易懂的Deno 入门教程

Deno 正式发布,彻底弄明白和 node 的区别

「实践」基于Apify+node+react/vue搭建一个有点意思的爬虫平台

「实践」深入对比 Vue 3.0 Composition API 和 React Hooks

前端网红框架的插件机制全梳理(axios、koa、redux、vuex)

深入Vue 必学高阶组件 HOC「进阶篇」

深入学习Vue的data、computed、watch来实现最精简响应式系统

10个实例小练习,快速入门熟练 Vue3 核心新特性(一)

10个实例小练习,快速入门熟练 Vue3 核心新特性(二)

教你部署搭建一个Vue-cli4+Webpack移动端框架「实践」

2020前端就业Vue框架篇「实践」

详解Vue3中 router 带来了哪些变化?

Vue项目部署及性能优化指导篇「实践」

Vue高性能渲染大数据Tree组件「实践」

尤大大细品VuePress搭建技术网站与个人博客「实践」

10个Vue开发技巧「实践」

是什么导致尤大大选择放弃Webpack?【vite 原理解析】

带你了解 vue-next(Vue 3.0)之 小试牛刀【实践】

带你了解 vue-next(Vue 3.0)之 初入茅庐【实践】

实践Vue 3.0做JSX(TSX)风格的组件开发

一篇文章教你并列比较React.js和Vue.js的语法【实践】

手拉手带你开启Vue3世界的鬼斧神工【实践】

深入浅出通过vue-cli3构建一个SSR应用程序【实践】

怎样为你的 Vue.js 单页应用提速

聊聊昨晚尤雨溪现场针对Vue3.0 Beta版本新特性知识点汇总

【新消息】Vue 3.0 Beta 版本发布,你还学的动么?

Vue真是太好了 壹万多字的Vue知识点 超详细!

Vue + Koa从零打造一个H5页面可视化编辑器——Quark-h5

深入浅出Vue3 跟着尤雨溪学 TypeScript 之 Ref 【实践】

手把手教你深入浅出vue-cli3升级vue-cli4的方法

Vue 3.0 Beta 和React 开发者分别杠上了

手把手教你用vue drag chart 实现一个可以拖动 / 缩放的图表组件

Vue3 尝鲜

总结Vue组件的通信

Vue 开源项目 TOP45

2020 年,Vue 受欢迎程度是否会超过 React?

尤雨溪:Vue 3.0的设计原则

使用vue实现HTML页面生成图片

实现全栈收银系统(Node+Vue)(上)

实现全栈收银系统(Node+Vue)(下)

vue引入原生高德地图

Vue合理配置WebSocket并实现群聊

多年vue项目实战经验汇总

vue之将echart封装为组件

基于 Vue 的两层吸顶踩坑总结

Vue插件总结【前端开发必备】

Vue 开发必须知道的 36 个技巧【近1W字】

构建大型 Vue.js 项目的10条建议

深入理解vue中的slot与slot-scope

手把手教你Vue解析pdf(base64)转图片【实践】

使用vue+node搭建前端异常监控系统

推荐 8 个漂亮的 vue.js 进度条组件

基于Vue实现拖拽升级(九宫格拖拽)

手摸手,带你用vue撸后台 系列二(登录权限篇)

手摸手,带你用vue撸后台 系列三(实战篇)

前端框架用vue还是react?清晰对比两者差异

Vue组件间通信几种方式,你用哪种?【实践】

浅析 React / Vue 跨端渲染原理与实现

10个Vue开发技巧助力成为更好的工程师

手把手教你Vue之父子组件间通信实践讲解【props、$ref 、$emit】

1W字长文+多图,带你了解vue的双向数据绑定源码实现

深入浅出Vue3 的响应式和以前的区别到底在哪里?【实践】

干货满满!如何优雅简洁地实现时钟翻牌器(支持JS/Vue/React)

基于Vue/VueRouter/Vuex/Axios登录路由和接口级拦截原理与实现

手把手教你D3.js 实现数据可视化极速上手到Vue应用

吃透 Vue 项目开发实践|16个方面深入前端工程化开发技巧【上】

吃透 Vue 项目开发实践|16个方面深入前端工程化开发技巧【中】

吃透 Vue 项目开发实践|16个方面深入前端工程化开发技巧【下】

Vue3.0权限管理实现流程【实践】

后台管理系统,前端Vue根据角色动态设置菜单栏和路由

作者: 徐小夕

转发链接:https://mp.weixin.qq.com/s/1nQdWmzOTSGXLAtHUC4Nhg

相关推荐

俄罗斯的 HTTPS 也要被废了?(俄罗斯网站关闭)

发布该推文的ScottHelme是一名黑客,SecurityHeaders和ReportUri的创始人、Pluralsight作者、BBC常驻黑客。他表示,CAs现在似乎正在停止为俄罗斯域名颁发...

如何强制所有流量使用 HTTPS一网上用户

如何强制所有流量使用HTTPS一网上用户使用.htaccess强制流量到https的最常见方法可能是使用.htaccess重定向请求。.htaccess是一个简单的文本文件,简称为“.h...

https和http的区别(https和http有何区别)

“HTTPS和HTTP都是数据传输的应用层协议,区别在于HTTPS比HTTP安全”。区别在哪里,我们接着往下看:...

快码住!带你十分钟搞懂HTTP与HTTPS协议及请求的区别

什么是协议?网络协议是计算机之间为了实现网络通信从而达成的一种“约定”或“规则”,正是因为这个“规则”的存在,不同厂商的生产设备、及不同操作系统组成的计算机之间,才可以实现通信。简单来说,计算机与网络...

简述HTTPS工作原理(简述https原理,以及与http的区别)

https是在http协议的基础上加了一层SSL(由网景公司开发),加密由ssl实现,它的目的是为用户提供对网站服务器的身份认证(需要CA),以至于保护交换数据的隐私和完整性,原理如图示。1、客户端发...

21、HTTPS 有几次握手和挥手?HTTPS 的原理什么是(高薪 常问)

HTTPS是3次握手和4次挥手,和HTTP是一样的。HTTPS的原理...

一次安全可靠的通信——HTTPS原理

为什么HTTPS协议就比HTTP安全呢?一次安全可靠的通信应该包含什么东西呢,这篇文章我会尝试讲清楚这些细节。Alice与Bob的通信...

为什么有的网站没有使用https(为什么有的网站点不开)

有的网站没有使用HTTPS的原因可能涉及多个方面,以下是.com、.top域名的一些见解:服务器性能限制:HTTPS使用公钥加密和私钥解密技术,这要求服务器具备足够的计算能力来处理加解密操作。如果服务...

HTTPS是什么?加密原理和证书。SSL/TLS握手过程

秘钥的产生过程非对称加密...

图解HTTPS「转」(图解http 完整版 彩色版 pdf)

我们都知道HTTPS能够加密信息,以免敏感信息被第三方获取。所以很多银行网站或电子邮箱等等安全级别较高的服务都会采用HTTPS协议。...

HTTP 和 HTTPS 有何不同?一文带你全面了解

随着互联网时代的高速发展,Web服务器和客户端之间的安全通信需求也越来越高。HTTP和HTTPS是两种广泛使用的Web通信协议。本文将介绍HTTP和HTTPS的区别,并探讨为什么HTTPS已成为We...

HTTP与HTTPS的区别,详细介绍(http与https有什么区别)

HTTP与HTTPS介绍超文本传输协议HTTP协议被用于在Web浏览器和网站服务器之间传递信息,HTTP协议以明文方式发送内容,不提供任何方式的数据加密,如果攻击者截取了Web浏览器和网站服务器之间的...

一文让你轻松掌握 HTTPS(https详解)

一文让你轻松掌握HTTPS原文作者:UC国际研发泽原写在最前:欢迎你来到“UC国际技术”公众号,我们将为大家提供与客户端、服务端、算法、测试、数据、前端等相关的高质量技术文章,不限于原创与翻译。...

如何在Spring Boot应用程序上启用HTTPS?

HTTPS是HTTP的安全版本,旨在提供传输层安全性(TLS)[安全套接字层(SSL)的后继产品],这是地址栏中的挂锁图标,用于在Web服务器和浏览器之间建立加密连接。HTTPS加密每个数据包以安全方...

一文彻底搞明白Http以及Https(http0)

早期以信息发布为主的Web1.0时代,HTTP已可以满足绝大部分需要。证书费用、服务器的计算资源都比较昂贵,作为HTTP安全扩展的HTTPS,通常只应用在登录、交易等少数环境中。但随着越来越多的重要...

取消回复欢迎 发表评论: