!
也想出现在这里? 联系我们
广告位

Vue 服务器端渲染

前端技术发展到今天,用户通过终端浏览到应用内容的方式一般包含两种:

  • 客户端渲染(CSR):客户端请求数据及 JS 内容,在客户端渲染成标准的页面呈现出来
  • 服务端渲染(SSR):服务端从本地拿到数据,然后先渲染好页面再发送到客户端呈现给用户

Vue.js 默认在客户端渲染页面,但是我们可以通过 vue-server-renderer 实现服务端渲染。 用流程图的方式描述二则的区别如下:
Vue 服务器端渲染

CSR 与 SSR 是页面渲染的两种方式,二则各有利弊:

客户端渲染(CSR:Client Side Render)
客户端渲染需要先从服务器拿到数据(主要是些 JS 文件),等这些必要的文件全部加载完后才会渲染页面,比如 Vue.js 中会先拿到一个简单的 html 文件,然后获取必要的 js 文件,通过 js 文件生成虚拟 DOM 用来展示页面。因此客户端渲染往往具有如下特点:

  • 初始加载慢,白屏时间长
  • 无 DOM 结构,不利于 SEO
  • 利于前后端分离,前端专注页面实现,后端专注于 API 开发
  • 用户体验好, 方便应用交互
  • 服务器压力小,页面渲染工作在客户端完成

服务端渲染(SSR:Server Side Render)
服务端渲染一般从本地拿到数据,根据数据渲染成前端可用的 html 页面,将页面发送给客户端快速显示,因此服务端渲染往往具有如下特点:

  • 服务器压力大,特别是对 Vue.js 需要根据客户请求创建独立的 vue 实例,防止数据污染
  • 用户发生交互行为后可能会频繁请求服务器
  • 不利于前后端分离,开发效率低,开发受限
  • 有利于 SEO,方便爬虫抓取数据
  • 首屏加载迅速,避免长时间白屏造成用户体验不好
  • 后端可生成静态缓存文件,避免大量数据库查询

先放两张图,对比下客户端渲染与服务端渲染,浏览器请求信息中的差异:
Vue 服务器端渲染
Vue 服务器端渲染
Vue 服务器端渲染
Vue 服务器端渲染

Vue 代码改造

Vue.js 是构建客户端应用程序的框架。默认情况下创建的应用程序是在浏览器中渲染并生成 DOM 和操作 DOM 的。也就是说,默认的 Vue 应用是客户端渲染(CSR)的,如果我们想让其在服务端渲染(SSR)就需要对其进行简单的改造。

为了避免服务端渲染造成的数据污染,我们需要通过工厂函数为每一个发起请求的用户创建独立的路由、状态管理、Vue实例。

createRouter

客户端渲染方式创建路由:

服务端渲染创建路由:

createStore

客户端渲染方式创建状态管理器:

服务端渲染方式创建状态管理器:

createApp

创建一个公共的文件 app.js ,方便客户端及服务端分别编译时调用。注意这里为方便区分没有直接改造 main.js。
客户端渲染方式创建 Vue 实例:

服务端渲染方式创建 Vue 实例:

entry-client.js

客户端编译时的入口文件,引入公共文件 app.js 中的代码后挂载实例。
注意:需要在 router.onReady 后挂载实例。

entry-server.js

服务端编译时的入口文件,引入公共文件 app.js 中的代码后

vue.config.js 改造

服务器端打包 JSON 数据,客户端打包静态文件,用于挂载实例。改造代码如下:

package.json 改造

将 package.json 中的 scripts 内容改成如下内容,这样就可以直接运行 npm run build 打包程序了。

服务器端渲染

要使用 vue-server-renderer 在服务器端渲染页面,我们需要先对其进行部署,这里以 node.js 服务器为例,使用 express 快速搭建服务器。

安装 vue-server-renderer

注意:vue-server-renderer 和 vue 必须匹配版本,且需要 node.js 环境支持

API 参考

因为之后的部署过程中可能用到相关 API ,这里先简单介绍一下。

  • createRenderer:使用(可选的)选项创建一个 Renderer 实例

  • createBundleRenderer:使用 server bundle 和(可选的)选项创建一个 BundleRenderer 实例

  • Class: Renderer
    • renderer.renderToString:将 Vue 实例渲染为字符串。上下文对象(context)可选。回调函数是的第一个参数是可能抛出的错误,第二个参数是渲染完毕的字符串。2.5.0+中,回调可选,默认返回 Promise 对象。

    • renderer.renderToStream:将 Vue 实例渲染为一个 Node.js 可读流。上下文对象(context)可选。

  • Class: BundleRenderer
    • bundleRenderer.renderToString:将 bundle 渲染为字符串。上下文对象(context)可选。回调的第一个参数是可能抛出的错误,第二个参数是渲染完毕的字符串。2.5.0+中,回调可选,默认返回 Promise 对象。

    • bundleRenderer.renderToStream:将 bundle 渲染为一个 Node.js 可读流。上下文对象(context)可选。

  • Renderer 选项
    • template:为整个页面的 HTML 提供一个模板。
    • clientManifest:通过此选项提供一个由 vue-server-renderer/client-plugin 生成的客户端构建 manifest 对象。
    • inject:控制使用 template 时是否执行自动注入。
    • shouldPreload:一个函数,用来控制什么文件应该生成 <link rel=”preload”> 资源预加载提示 (resource hints)。
    • shouldPrefetch:一个函数,用来控制对于哪些文件,是需要生成 <link rel=”prefetch”> 资源提示。
    • runInNewContext:只用于 createBundleRenderer,是否每次渲染都创建一个新的 V8 上下文并重新执行整个 bundle。
    • basedir:只用于 createBundleRenderer,显式地声明 server bundle 的运行目录。运行时将会以此目录为基准来解析 node_modules 中的依赖模块。
    • cache:提供组件缓存具体实现。
    • directives:对于自定义指令,允许提供服务器端实现。

server/index.js 代码

npm 安装

给TA打赏
共{{data.count}}人
人已打赏
编程技术

宝塔面板 MySQL 无法启动,备份好你的数据库

2022-9-3 16:31:08

编程技术

Vue 你需要知道的一些事

2022-9-3 16:31:43

声明 本站上的部份代码及教程来源于互联网,仅供网友学习交流,若您喜欢本文可附上原文链接随意转载。无意侵害您的权益,请发送邮件至 admin@s9h.cn 或点击右侧 私信:少羽 反馈,我们将尽快处理。
0 条回复A文章作者M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索