最近两个项目同时开发,使用了Vue2的SSR,这样后端渲染页面首屏可以加快页面呈现,增加SEO和用户体验,但是项目上线后却发现了严重的性能问题,于是在三天内两次重大调整,最后只能放弃Vue SSR,本文从Vue SSR实现开始,逐渐复盘整个事件。
两周前就预告了要写一篇Vue SSR的文章,但是没想到上周四上线之后,周六放量之后发现性能问题,这周一到周三,做了两次重大调整,最终还是放弃了SSR,并且做了这次事件复盘。

技术选型

调研Vue已经很久了,随着Vue2正式发布,使用Vue来做项目又燃起了希望,不是为了一时的技术理想和情怀(了解我的人都知道,我不是这样的人),主要是出于下面几方面考虑:

  1. 用artTemplate+Sass+JS做的components方案已经做了很久了,沉淀了很多组件,随着Node服务开始上线,一直想在此基础上做同构,而公司Node框架Yog2的view层选择偏向于Smarty模板的Swig,修改比较麻烦
  2. 既然改不了,那么要换不如直接选择新的components方案,这次最强烈需求是:组件化和支持SSR,而Vue2之后支持SSR
  3. 这次两个项目同时进行,而且仅仅给两周的开发时间,组件化有效提高工作效率,可以把通用的组件抽象出来,多个页面之间业务组件复用率也很高,而且业务组件在后续的运营活动也可以直接复用
  4. 手百产品形态复杂,页面即在手百内使用又有手百外使用,手百内页面被多个Webview隔开,不适合SPA形式,而手百外适合SPA形式,所以一套代码需要适配两种情况,Vue 可以适应这两种方式
  5. Vue的SPA形式可以方便进行PWA和Hybrid改造(继续关注本公众号Hybrid系列)

所以,最后决定:上Vue!技术栈:Vue2+Yog2

再介绍下两个项目:

  • 项目A是老项目进行重构,产品需求要跟功能全部保留,架构跑通使用的是Vue2.1,所以A项目代码相对复杂,一直没有使用Vue2.2
  • 项目B是新项目,开始使用Vue2.1,上线后发现已经有Vue2.2,于是升级Vue2.2,并且把项目目录结构调整一番,Webpack config等都可配
    Vue SSR入门到上线

先看下Vue SSR的实现流程图:

简单解释一下:

  1. app.js是Server和Client公用的
  2. webpack会根据server-entry.js和client-entry.js打包出来两个文件:server-bundle和client-bundle
  3. server-bundle用于后端渲染(2.1是js文件,2.2变成json,引入更加方便)

但是这张图没有说明在调用API接口方面,前后端是怎么公用代码的。前端走的是Ajax请求,后端走的是http请求(百度内部是RAL接口服务管理),结合上图补充完整的代码执行流程图如下:

webpack区分接口请求方式

在浏览器内使用ajax请求,而在服务端需要调用内部API请求或者直接读取存储(RAL)。ajax请求到达服务端依次经过:action层、model层,最后走到还是API请求或者读取数据(这里重点读三遍。。)。

这里我们将服务端和客户端API的请求方法写在不同的文件内,但是封装暴漏的接口都是一样的(接口模式)。在webpack里面,针对server和client提供不同的alias:

这样 require('api/demo') 的时候,会区分开server和client。

server内直接使用yog2 modal内的获取数据方法,比如:

而client内,直接使用ajax请求:

Vue内使用Vuex来获取数据

即下图的流程:

在渲染的时候,prefetch阶段通过dispatch触发Store的Action(Action内允许异步),Action内调用 api/demo 获取数据成功后commit mutation,这样整个数据就跑通了。

server.js

server.js是第一次渲染使用的入口action,核心代码如下:

//vue2.2
const vueServerRender = require('vue-server-renderer');
const bundle = require('../vue-ssr-bundle.json');
const renderer = vueServerRender.createBundleRenderer(bundle, {template: '<!--vue-ssr-outlet-->',cache: require('lru-cache')({max: 1000,maxAge: 1000 * 60 * 15})
})
// 先渲染tpl(swig模板),内容类似vue ssr demo的index.html
// 这里渲染使用chunk,先输出不依赖数据的头部html
res.render('page/index.tpl', { isSendSpeedCode }, (err, html) => {if (!err) {var htmls = html.split('<!--vue-ssr-outlet-->')//先渲染头部htmlres.write(htmls[0])// swig渲染时间var time1 = Date.now()const renderStream = renderer.renderToStream(context)renderStream.on('data', chunk => {// 边解析,边渲染htmlres.write(chunk)})renderStream.on('end', () => {if (isSendSpeedCode) {// 统计vue 渲染时间var time2 = Date.now()var code = `<script>if(window.alog){alog('speed.set', 'p_swig', ${time1 - time0});alog('speed.set', 'p_vue', ${time2 - time1});}</script>`res.write(code)}// 渲染尾部htmlres.end(htmls[1])}).on('error', errorHandler)} else {errorHandler(err)}
})复制代码

Webpack和FIS3两次编译

webpack是vue「全家桶」的后遗症,项目太急没办法去掉。我们项目的目录结构如下:

项目需要两次打包:

  1. 第一次是webpack,webpack把 vue-src文件夹内容根据 server-entryclient-entry打包出来,分别放进yog2的client和server对应的文件,之后 vue-src在执行环境就不需要了
  2. 第二次是FIS3的打包,会按照Yog2的规范release出来可以上线的内容

这里有个细节:webpack打包出来的静态资源路径需要跟FIS3打包的静态资源路径一致,不然就没法通过FIS3进行静态资源定位,比如替换为CDN地址。
由于vue2.2打出来的server-bundle是json格式文件,所以FIS无法将json内的静态资源进行统一管理,需要webpack判断生产环境直接替换为CDN地址

遇见的其他问题和技巧

client代码在server上跑

手百的通用库Bdbox是client代码,代码中有一些window全局变量的使用,而我们知道Node是没有 window的,在Node执行SSR的时候,会报错,比如下面的代码:

// 自执行
isAndroid: /(Android);?[\s\/]+([\d.]+)?/.test(navigator.userAgent)复制代码

有两种改法:

  1. .isAndroid由属性变成方法:.isAndroid(),放到mount内执行
  2. 给vue-server-renderer传入带有navigator.userAgent的context

利用resolve.alias

目录结构深了,尤其是Vue里面还需要调用yog model的代码,会各种../../很蛋疼,可以利用alias简化写法:

需要注意的是static的写法是:<img src=“~static/img/logo.png”

利用Yog2 的 Mock功能进行测试

订好接口请求参数和返回数据格式之后,后端RD进行API的编写同时,我们可以利用Yog2的Mock功能,对ral返回的数据进行假数据测试,实现后端和前端RD解耦,大大提高开发效率。

Vue SSR从上线到Case Study

现在来复盘下整个事件:

  1. 4月5日,完成代码开发,全功能提测,开始倒腾上线,晚上第一次上线成功,基本功能回归没问题,
  2. 紧接着几次bug修复上线,6号周四上线日,基本没有问题了
  3. 4月7日开始APP审核通过,放量开始,这时候发现随着流量上升,服务器扛不住了
  4. 8日(周六)紧急添加实例,周末算是硬扛过去了
  5. 10(周一)排查原因,发现内存可能存在泄漏和性能问题,增加打点统计后端渲染时间,但是VM相对来说是黑盒,性能不好排查
  6. 11日(周二)增加lru-cache,细化组件缓存,下午上线后,晚上发现内存曲线更加严重,于是晚上10点回滚lru和组件缓存代码,随版本收敛影响,流量继续上涨,增加机器实例
  7. 12日(周三)采取降级方案,第一次进入页面将API数据放到以变量形式放到页面,然后增加beforeCreate阶段代码,将页面数据直接commit给mutation进行渲染,曲线开始平缓
  8. 13日(周四)观察一晚曲线没有问题,中午开始缩容(下线实例)

从周一到周三经过两次大的调整,终于服务稳定了,其中代码review阶段,我们也发现了很多代码不规范的现象。下面来说下我们使用vue ssr的一些压测等数据。

单实例QPS、内存和CPU数据

从上线之后,内存积累到一定时间就飙升,内存飙升同时,CPU也进行飙升,具体曲线如下:

从12日(周三19点)上线之后,就开始平稳了,13日中午缩容后,CPU稍有上扬。

同期QPS的数据如下:

查看全文,关注微信公众号:「三水清」(sanshuiqing123)

Vue SSR 从入门到 Case Study相关推荐

  1. vue ssr java_Vue-SSR入门

    一.下载安装 $ npm install express-generator -g 使用express命令创建项目(-e:ejs模板引擎) $ express -e myapp 2.下载 vue vu ...

  2. Vue SSR 渲染 Nuxt3 入门学习

    Vue SSR 渲染 Nuxt3 入门学习 SPA应用:也就是单页应用,这些多是在客户端的应用,不利于进行SEO优化(搜索引擎优化). SSR应用:在服务端进行渲染,渲染完成后返回给客户端,每个页面有 ...

  3. Vue学习(入门实例、常用指令)-学习笔记

    文章目录 Vue学习(入门实例.常用指令)-学习笔记 实例 常用指令 v-on v-bind v-for v-html v-if event v-model 双向数据绑定实现 - defineProp ...

  4. Vue与Element入门使用

    Vue: Vue是一套构建用户界面的渐进式前端框架. 只关注视图层,并且非常容易学习,还可以很方便的与其它库或已有项目整合. 通过尽可能简单的API来实现响应数据的绑定和组合的视图组件. 视图:负责页 ...

  5. 关于Vue ssr的一点探讨

    这很难,里面只是我以比较明显的一个问题,引发对整个ssr的研究.但是我又复习了下Vuex,发现了异步问题.过两天把router也复习了.那异步问题应该就解决了,到时候再出篇稿子.这篇,你可能看不懂,因 ...

  6. 前端-Vue.js从入门到精通基础笔记(理论+实操+知识点速查)

    #[2022.3]尚硅谷Vue.js从入门到精通基础笔记(理论+实操+知识点速查) 前言 本文完全基于 参考资料:加工整理而成,包括其代码,案例,资源等.前置知识是学习尚硅谷的视频教程,本文配合其教程 ...

  7. Case study:在数据库网页中设计数据排序工具

    一.目的 该笔记的目的是引导读者在已搭建的数据库网页的基础上,利用JS设计数据排序工具.其效果如图1所示."Order by"下拉列表框由一系列字段组成,如"Locati ...

  8. Case Study: 利用PHP获取关系型数据库中多张数据表的数据

    一.目标 该笔记的目的是引导读者借助WampServer平台和MySQL数据库,利用HTML/CSS/JS/PHP设计一个多数据表关联的网页.在上一个案例(Case Study: 利用JS实现数据库网 ...

  9. Case Study: 利用JS实现数据库网页的数据分页、数据选择、数据详细信息查看功能

    一.目标 该笔记的目的是引导读者借助WampServer平台和MySQL数据库,利用HTML/CSS/JS/PHP设计一个能够进行实现数据分页显示.数据选择.数据详细信息查看功能的数据库网页.该数据库 ...

最新文章

  1. python3报错处理:UnicodeEncodeError: ‘ascii‘ codec can‘t encode characters in position 0-1
  2. 为何从单体架构迁移到微服务这么难?
  3. linux软件升级直接替换,Linux几个命令的升级替代品
  4. Spring - Java/J2EE Application Framework 应用框架
  5. 12123两小时没付款怎么办_交管12123支付宝小程序付款不了怎么办 交管12123支付宝缴费方法介绍[多图]...
  6. 一个七年的老测试给想入行软件测试这个行业的二十条建议
  7. 【转】推荐一款Java反编译器,比较好用
  8. linux tomcat 7.0下载 64位,tomcat 7.0下载
  9. 系统架构设计师考试大纲 考点
  10. (QACNN)自然语言处理:智能问答 IBM 保险QA QACNN 实现笔记
  11. Ubuntu下Rhythmbox乱码的解决办法
  12. 计算机伦理学理论分析三大思想,试论伦理学的三种理论形态——基于理论形态学的考察...
  13. SpringMVC 上传文件或图片并以二进制流的方式存到数据库
  14. 西安交大计算机学院 栾佳锡,史椸-西安交通大学-自动化科学与工程学院
  15. 快递物流查询,教你自动查询并识别所有快递是否签收、退回
  16. python模型预测_用Python如何进行预测型数据分析
  17. LATEX公式下标短横线过长
  18. windows电脑无线投屏到小米电视
  19. CodeForces - 514B Han Solo and Lazer Gun
  20. 为什么直通车关键词点击率和转化率会低

热门文章

  1. perl mysql 数据推拉_科学网—从MySQL数据库中提取序列并进行引物设计的perl脚本 - 闫双勇的博文...
  2. 分布式架构实现概述(大型网站技术架构-读后感)
  3. java语音播报源代码_详解Android 语音播报实现方案(无SDK)
  4. 33 Qt 之绘图之绘制卡通蚂蚁
  5. [易学易懂系列|golang语言|零基础|快速入门|(二)]
  6. windows下的python安装scrapy
  7. php抓取栏目id,phpcms v9 根据栏目id( catid ) 获取栏目名称
  8. 在程序员行业,找师傅跟找对象差不多,这些点你得注意!
  9. currency translation BW 货币转换
  10. 群辉中安装openwrt