快速在你的vue/react应用中实现ssr(服务端渲染)

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

前言


我们都知道, 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属性。


  1. renderToStaticMarkup:将 React Component 转化为 HTML 字符串,但是生成 HTML 的 DOM 不会有额外属性,从而节省 HTML 字符串的大小。


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


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


Google 推出的 Rendertron 使得 SPA 也能够被不支持执行 Javascript 的搜索引擎爬取渲染后的内容。其原理主要是通过使用 HeadlessChrome 在内存中执行 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. 但是我们需要考虑当网站流量增加时的扩容问题,以及配置搭建反向代理或负载均衡等配套服务。


后期展望


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


目录
相关文章
|
1月前
Vue3只渲染一次 v-once
Vue3只渲染一次 v-once
|
20天前
|
JavaScript 前端开发 索引
Vue嵌套循环渲染与条件渲染--v-for|v-if
Vue嵌套循环渲染与条件渲染--v-for|v-if
20 0
|
5天前
|
JavaScript 前端开发 API
vue改变数组页面重新渲染的操作/那些操作不会重新渲染页面以及解决方法
vue改变数组页面重新渲染的操作/那些操作不会重新渲染页面以及解决方法
14 2
|
24天前
|
JavaScript 前端开发 UED
Vue工具和生态系统: Vue.js和服务器端渲染(SSR)有关系吗?请解释。
Vue.js是一个渐进式JavaScript框架,常用于开发单页面应用,但其首屏加载较慢影响用户体验和SEO。为解决此问题,Vue.js支持服务器端渲染(SSR),在服务器预生成HTML,加快首屏速度。Vue.js的SSR可手动实现或借助如Nuxt.js的第三方库简化流程。Nuxt.js是基于Vue.js的服务器端渲染框架,整合核心库并提供额外功能,帮助构建高效的应用,改善用户体验。
20 0
|
1月前
|
JavaScript 前端开发
vue 条件渲染
vue 条件渲染
|
1月前
|
JavaScript 前端开发 索引
vue 列表渲染
vue 列表渲染
|
1月前
|
JavaScript
Vue 路由切换时页面刷新页面重新渲染
在Vue中,路由切换并不自动重新渲染页面,这可能导致传递参数到子组件时出现问题。使用`this.$route.replace(&#39;地址&#39;)`或`this.$route.push({name:&#39;地址&#39;,params:{key:value}})`进行跳转,但子组件不会响应变化。为解决此问题,需监听`$route`对象的变化,如图所示,通过`watch: {$route}`确保页面更新。
|
19天前
|
前端开发 测试技术 开发工具
探索前端框架React Hooks的优势与应用
本文将深入探讨前端框架React Hooks的优势与应用。通过分析React Hooks的特性以及实际应用案例,帮助读者更好地理解和运用这一现代化的前端开发工具。
|
12天前
|
开发框架 Dart 前端开发
【Flutter前端技术开发专栏】Flutter与React Native的对比与选择
【4月更文挑战第30天】对比 Flutter(Dart,强类型,Google支持,快速热重载,高性能渲染)与 React Native(JavaScript,庞大生态,热重载,依赖原生渲染),文章讨论了开发语言、生态系统、性能、开发体验、学习曲线、社区支持及项目选择因素。两者各有优势,选择取决于项目需求、团队技能和长期维护考虑。参考文献包括官方文档和性能比较文章。
【Flutter前端技术开发专栏】Flutter与React Native的对比与选择
|
11天前
|
前端开发 JavaScript 开发者
【专栏:HTML与CSS前端技术趋势篇】前端框架(React/Vue/Angular)与HTML/CSS的结合使用
【4月更文挑战第30天】前端框架React、Vue和Angular助力UI开发,通过组件化、状态管理和虚拟DOM提升效率。这些框架与HTML/CSS结合,使用模板语法、样式管理及组件化思想。未来趋势包括框架简化、Web组件标准采用和CSS在框架中角色的演变。开发者需紧跟技术发展,掌握新工具,提升开发效能。