细说Vue组件的服务器端渲染的过程

声明:需要读者对 NodeJs、Vue 服务器端渲染有一定的了解

现在,前后端分离与客户端渲染已经成为前端开发的主流模式,绝大部分的前端应用都适合用这种方式来开发,又特别是 React、Vue 等组件技术的发展,更是使这种方式深入人心。

但有一些应用,客户端渲染就会遇到一些问题了:

  • 需要做 SEO(搜索引擎优化),但客户端渲染的 html 中几乎没有可用的信息
  • 需要首屏快速加载,但客户端渲染一般是长时间的加载动画或者白屏

如果能把客户端渲染的组件化技术(React、Vue 等)与传统的后端渲染的方式有效的结合起来,两者兼具,那就太完美了。

所以,这次就来聊聊 Vue 组件的服务器端渲染。

根据社区现有的一些方案,结合自己的实践,针对团队技术力量的不同,说说不同应用场景选择方案时的优先级。

1. NodeJs 渲染中间层

一般前后端的工作流是 后端 -> 前端

传统的后端渲染模式是后端负责包括 url、接口、模板渲染等,前端与后端耦合在一起,当然这种方式正在慢慢的退出历史舞台。

主流的客户端渲染则是后端只提供接口(如有需要,可以提供必要的 url),前端与后端只通过接口交流数据,路由与渲染都在前端完成。

而 NodeJs 渲染中间层的工作流则是 后端 -> NodeJs -> 前端(NodeJs 渲染中间层由前端开发人员掌握)。

这种模式下,后端只提供接口,传统的服务器端路由(url)、模板渲染则都有 NodeJs 层接管。这样,前端开发人员可以自由的决定哪些组件需要在服务器端渲染,哪些组件可以放在客户端渲染,前后端完全解耦,但又保留了服务器端渲染的功能。

这种方案最成熟的是nuxt.js

如果有需要,大家可以自己去 nuxt.js 官方文档 看看具体的使用方法和详细的功能。

应该说,这种方式是目前最完美的一种方案,但也有一些隐患:

  • 增加了一个 NodeJs 中间层,应用性能会有所降低
  • 增加了架构的复杂度、不稳定性,也降低了应用的安全性
  • 对于高并发应用,NodeJs 层会很容易形成瓶颈
  • 对开发人员要求高了很多

所以,这种方式适合对并发量、安全性、稳定性等要求不高,但又需要做 SEO 或首屏快速加载的页面。

当然,如果你能够自己改造相关的工具,就另当别论了。

2. 保留后端模板渲染

当不能使用 NodeJs 中间层时,而又要达到 SEO 与首屏快速响应的目的时,在传统的后端模板渲染的基础上,就需要对前端的页面加以适当的改造。

2.1 首屏快速响应

首屏快速响应就意味着首屏渲染所需的数据是跟 HTML 文件一起到达浏览器的,这些数据当前是由后端模板引擎嵌入到 HTML 页面中的。

以 Java 的 freemarker模板引擎为例:

html 中以 script 的方式获取模板的数据,这样就算是在本地调试、开发,也不会报错)。

<script>
 window.globalData = {
  stringValue: '${stringValueTplName}',
  intValue: parseInt('${intValueTplName}', 10),
 };
</script>

如果是复杂的 Json 数据或者其他复杂的模板数据(比如列表数据),则可以像下面这样接收:

<script type="text/tpl" id="tpl-script-json">
 window.tmpData = {
  jsonValue: ${jsonValueTplName},
 };
</script>

<script>
 try {
  eval(document.getElementById('tpl-script-json').innerText);
 } catch (e) {
  window.tmpData = { jsonValue: {} };
 }

 window.globalData = {
  jsonValue: window.tmpData.jsonValue,
 };
</script>

这样,你就可以在组件里使用 window.globalData 的数据了,而不用另外用接口获取数据,达到加快首屏渲染的目的,而且本地开发、调试也不会报错。

如果你使用了本地数据 Mock 功能,也可以很容易的与这种方式结合在一起,只要稍加改造:

  1. 在代码中定义本地和服务器两个环境,本地环境使用 Mock 数据,服务器环境使用 window.globalData
  2. 可以使用see-ajax, see-fetch来简化这种方式的开发

此外,还有一些措施来进一步加快首屏渲染:

  • 尽量减少首屏加载的脚本文件大小,其他脚本可以按需加载
  • 如果需要,可以将 CSS、JS 内容注入到 HTML 中,这样就只会发起一个请求,也可以加快加载速度

2.2 SEO 优化

在上面加载首屏渲染的基础上,对于 SEO 优化也可以做相应的改造。

其实,在客户端渲染已慢慢成为主流开发模式的同时,搜索引擎也在跟进这种变化。

截至目前,Google 和 Bing 可以很好对同步 JavaScript 应用程序进行索引,也就是说,即使是客户端渲染,但只要是同步数据渲染(非 Ajax 获取数据,比如模板数据),搜索引擎也能抓取到相应的 HTML 片段。

(国内的百度搜索与360搜索等暂时还没有跟进动态)

但为了兼容所有的搜索引擎,可以像下面改造:

先由后端模板引擎渲染一些 HTML 片段,仅给搜索引擎抓取,不作为给用户展示的页面

然后再由客户端渲染同步或异步的数据给用户展示真正的页面

<div>
 <!-- 这里放置由后端模板引擎渲染的专给搜索引擎抓取的片段,用户不可见 -->
</div>

<script>
 // 接收同步数据
 window.globalData = {
  stringValue: '${stringValueTplName}',
  intValue: parseInt('${intValueTplName}', 10),
 };
</script>

3. 导出静态 html

如果页面没有动态数据,那就好办了,直接把组件导出为静态 html,然后由客户端激活。

具体过程可以参考 官方文档

这种方案比较好的是 nuxt.jsgenerate 静态 HTML 文件。

目录结构:

- pages/        # 页面结构目录
 - index.vue
 - second.vue
 - ...
- nuxt.config.js    # 配置文件
- package.json

- dist         # 导出静态 HTML 文件的默认目录 

导出静态 HTML 文件

npx nuxt generate

如果一个项目里有多个 pages,可以这样构建:

目录结构:

- nuxt.config.js    # 配置文件
- package.json

- src/
 - home/        # home 页面
  - pages/      # 页面结构目录
   - index.vue
   - second.vue
   - ...

  - dist       # 导出静态 HTML 文件的默认目录
 - about/       # about 页面
  - pages/      # 页面结构目录
   - index.vue
   - second.vue
   - ...

  - dist       # 导出静态 HTML 文件的默认目录  

导出静态 HTML 文件

npx nuxt generate src/home -c ../../nuxt.config.js  # home 页面
npx nuxt generate src/about -c ../../nuxt.config.js  # about 页面

除了上面提到的这些方式外,当然还有其他的方式,比如:

使用 Chrome Headless 模式获取组件的静态 HTML,参考 react-snap, puppeteer

官方 vue-server-renderer导出静态 HTML

4. 总结

因为模式的改变,服务器端渲染与传统的后端模板渲染工作方式有很大的不同,所以在开发时需要与后端开发人员做好沟通,避免认知上的不同导致协作不协调。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Vue服务器渲染Nuxt学习笔记

    关于SSR的文章网上很多,一开始看得我云里雾里.然后去Vue.js 服务器渲染指南和nuxt官网看了看,发现文章大多都是搬运官网的内容,真正讲的清晰明了的很少.所以想写篇文章学习下SSR,希望能够帮助大家快速理解Vue SSR. 什么是SSR? SSR,即服务器渲染,就是在服务器端将对Vue页面进行渲染生成html文件,将html页面传给浏览器. 优点: SEO 不同于SPA的HTML只有一个无实际内容的HTML和一个app.js,SSR生成的HTML是有内容的,这让搜索引擎能够索引到页面内容.

  • Vuejs中使用markdown服务器端渲染的示例

    啊哈,又是来推荐一个 vuejs 的 package,miaolz123/vue-markdown. 对应的应用场景是:你想使用一个编辑器或者是在评论系统中支持 markdown.这个 package 的有点还是挺多了,比如默认就支持 emoji,这个就很完美啦!laravist 的新版就使用了 vue-markdown 来渲染评论. 安装 直接使用 npm 来安装: npm install --save vue-markdown 使用 也是很简单的,可以直接这样: import VueMark

  • 细说Vue组件的服务器端渲染的过程

    声明:需要读者对 NodeJs.Vue 服务器端渲染有一定的了解 现在,前后端分离与客户端渲染已经成为前端开发的主流模式,绝大部分的前端应用都适合用这种方式来开发,又特别是 React.Vue 等组件技术的发展,更是使这种方式深入人心. 但有一些应用,客户端渲染就会遇到一些问题了: 需要做 SEO(搜索引擎优化),但客户端渲染的 html 中几乎没有可用的信息 需要首屏快速加载,但客户端渲染一般是长时间的加载动画或者白屏 如果能把客户端渲染的组件化技术(React.Vue 等)与传统的后端渲染的

  • vue组件是如何解析及渲染的?

    前言 本文将对vue组件如何解析以及渲染做一个讲解. 我们可以通过Vue.component注册全局组件,之后可以在模板中进行使用 <div id="app"> <my-button></my-button> </div> <script> Vue.component("my-button", { template: "<button> 按钮组件</button>"

  • Vue组件大全包括(UI组件,开发框架,服务端,辅助工具,应用实例,Demo示例)

    Vue是一款比较流行的JS库,本文为大家介绍一些Vue组件,包括UI组件,开发框架,服务端,辅助工具,应用实例,Demo示例等开源项目 一.Vue常用UI组件 element ★11612 - 饿了么出品的Vue2的web UI工具套件 Vux ★7503 - 基于Vue和WeUI的组件库 iview ★5801 - 基于 Vuejs 的开源 UI 组件库 mint-ui ★5517 - Vue 2的移动UI元素 vue-material ★2790 - 通过Vue Material和Vue 2

  • 详解vue 组件

    Vue的两大核心 1. 数据驱动 - 数据驱动界面显示 2. 模块化 - 复用公共模块,组件实现模块化提供基础 组件基础 组件渲染过程 template ---> ast(抽象语法树) ---> render ---> VDom(虚拟DOM) ---> 真实的Dom ---> 页面 Vue组件需要编译,编译过程可能发生在 打包过程 (使用vue文件编写) 运行时(将字符串赋值template字段,挂载到一个元素上并以其 DOM 内部的 HTML 作为模板) 对应的两种方式 r

  • 详解Vue.js3.0 组件是如何渲染为DOM的

    本文主要是讲述 Vue.js 3.0 中一个组件是如何转变为页面中真实 DOM 节点的.对于任何一个基于 Vue.js 的应用来说,一切的故事都要从应用初始化「根组件(通常会命名为 APP)挂载到 HTML 页面 DOM 节点(根组件容器)上」说起.所以,我们可以从应用的根组件为切入点. 主线思路:聚焦于一个组件是如何转变为 DOM 的. 辅助思路: 涉及到源代码的地方,需要明确标记源码所在文件,同时将 TS 简化为 JS 以便于直观理解 思路每前进一步要能够得出结论 尽量总结归纳出流程图 应用

  • Vue组件的渲染流程详细讲解

    目录 引言与例子 举一个工作中能用到的例子: 实现 extend 执行流程 1. 注册流程(以Vue.component()祖册为例子): 2. 执行流程 3. 渲染流程 总结 注: 本文目的是通过源码方向来讲component组件的渲染流程 引言与例子 在我们创建Vue实例时,是通过new Vue.this._init(options)方法来进行初始化,然后再执行$mount等,那么在组件渲染时,可不可以让组件使用同一套逻辑去处理呢? 答:当然是可以的,需要使用到Vue.extend方法来实现

  • Vue 组件渲染详情

    目录 前言 全局组件 Vue.extend 组件渲染流程 总结 前言 Vue中组件分为全局组件和局部组件: 全局组件:通过Vue.component(id,definition)方法进行注册,并且可以在任何组件中被访问 局部组件:在组件内的components属性中定义,只能在组件内访问 下面是一个例子: <div id="app"> {{ name }} <my-button></my-button> <aa></aa> &

  • 加速vue组件渲染之性能优化

    背景 平时在用vue开发后台管理系统的时候,应该会用到大量的table这种组件,正常这种组件我们会在项目里做二次封装,然后针对表头title做参数化配置,如下: export default { data(){ return { tableTitle:[ { label:'省份', prop:'prop' }, { label:'城市', prop:'prop' }, { label:'汇总', prop:'prop', colconfig:[ { label:'下级', prop:'prop'

  • Vue切换Tab动态渲染组件的操作

    使用<component :is="组件名"></component> 结合Element-UI的导航菜单 : UI组件 el-menu-item里的index写对应的组件名 点击事件@select="handleSelect" <el-menu :default-active="activeIndex" class="el-menu-demo" mode="horizontal&quo

随机推荐