Vue 实战:武装你的前端项目

本文项目基于Vue-Cli3,想知道如何正确搭建请看我之前的文章:

「Vue实践」项目升级vue-cli3的正确姿势

1. 接口模块处理

1.1 axios 二次封装

很基础的部分,已封装好的请跳过。这里的封装是依据 JWT

紧接着的是响应拦截器(即异常处理)

这里做的处理分别是会话已失效和登陆超时,具体的需要根据业务来作变更。

最后是导出基础请求类型封装。

其中给 get 请求加上时间戳参数,避免从缓存中拿数据。

浏览器缓存是基于url进行缓存的,如果页面允许缓存,则在一定时间内(缓存时效时间前)再次访问相同的URL,浏览器就不会再次发送请求到服务器端,而是直接从缓存中获取指定资源。

1.2 请求按模块合并

模块的请求:

utils/api/index.js :

1.3 global.js中的处理

global.js 中引入:

写接口的时候就可以简化为:

2.Vue组件动态注册

来自 @SHERlocked93:Vue 使用中的小技巧

我们写组件的时候通常需要引入另外的组件:

写小项目这么引入还好,但等项目一臃肿起来…啧啧。 这里是借助 webpack ,使用  require.context() 方法来创建自己的模块上下文,从而实现自动动态  require 组件。

这个方法需要3个参数:

  • 要搜索的文件夹目录

  • 是否还应该搜索它的子目录

  • 一个匹配文件的正则表达式。

在你放基础组件的文件夹根目录下新建 componentRegister.js :

最后我们在 main.js

我们就可以随时随地使用这些基础组件,无需手动引入了。

3. 页面性能调试:Hiper

我们写单页面应用,想看页面修改后性能变更其实挺繁琐的。有时想知道是「正优化」还是「负优化」只能靠手动刷新查看 network 。而  Hiper 很好解决了这一痛点(其实  Hiper 是后台静默运行  Chromium 来实现无感调试)。

Hiper官方文档

我们开发完一个项目或者给一个项目做完性能优化以后,如何来衡量这个项目的性能是否达标?

我们的常见方式是在 DevTool 中的  performance 和  network 中看数据,记录下几个关键的性能指标,然后刷新几次再看这些性能指标。

有时候我们发现,由于样本太少,受当前「网络」、「CPU」、「内存」的繁忙程度的影响很重,有时优化后的项目反而比优化前更慢。

如果有一个工具,一次性地请求N次网页,然后把各个性能指标取出来求平均值,我们就能非常准确地知道这个优化是「正优化」还是「负优化」。

并且,也可以做对比,拿到「具体优化了多少」的准确数据。这个工具就是为了解决这个痛点的。

安装

性能指标

Key Value
DNS查询耗时 domainLookupEnd – domainLookupStart
TCP连接耗时 connectEnd – connectStart
第一个Byte到达浏览器的用时 responseStart – requestStart
页面下载耗时 responseEnd – responseStart
DOM Ready之后又继续下载资源的耗时 domComplete – domInteractive
白屏时间 domInteractive – navigationStart
DOM Ready 耗时 domContentLoadedEventEnd – navigationStart
页面加载总耗时 loadEventEnd – navigationStart

用例

此外,还可以配置 Cookie 访问

4. Vue高阶组件封装

我们常用的 和  就是一个高阶(抽象)组件。

所有的高阶(抽象)组件是通过定义 abstract 选项来声明的。高阶(抽象)组件不渲染真实  DOM 。 一个常规的抽象组件是这么写的:

4.1 防抖/节流 抽象组件

关于防抖和节流是啥就不赘述了。这里贴出组件代码:

改编自:Vue实现函数防抖组件

通过第三个参数 isDebounce 来控制切换防抖节流。 最后在  main.js 里引用:

使用:

使用:

抽象组件是一个接替Mixin实现抽象组件公共功能的好方法,不会因为组件的使用而污染DOM(添加并不想要的div标签等)、可以包裹任意的单一子元素等等

至于用不用抽象组件,就见仁见智了。

5. 性能优化:eventBus封装

中央事件总线eventBus的实质就是创建一个vue实例,通过一个空的vue实例作为桥梁实现vue组件间的通信。它是实现非父子组件通信的一种解决方案。

eventBus 实现也非常简单

我们在使用中经常最容易忽视,又必然不能忘记的东西,那就是: 清除事件总线  eventBus

不手动清除,它是一直会存在,这样当前执行时,会反复进入到接受数据的组件内操作获取数据,原本只执行一次的获取的操作将会有多次操作。本来只会触发并只执行一次,变成了多次,这个问题就非常严重。

当不断进行操作几分钟后,页面就会卡顿,并占用大量内存。

所以一般在vue生命周期 beforeDestroy 或者  destroyed 中,需要用vue实例的  $off 方法清除  eventBus

可当你有多个 eventBus 时,就需要重复性劳动  $off 销毁这件事儿。 这时候封装一个  eventBus 就是更佳的解决方案。

5.1 拥有生命周期的 eventBus

我们从Vue.init中可以得知:

每个Vue实例有自己的  _uid 作为唯一标识,因此我们让  EventBus 和_uid`关联起来,并将其改造:

实现来自:让在Vue中使用的EventBus也有生命周期

使用:

组件中使用:

6. webpack插件:真香

6.1 取代 uglifyjs 的  TerserPlugin

在二月初项目升级Vue-cli3时遇到了一个问题: uglifyjs 不再支持webpack4.0。找了一圈,在  Google 搜索里查到  TerserPlugin 这个插件。

我主要用到了其中这几个功能:

  • cache ,启用文件缓存。

  • parallel ,使用多进程并行来提高构建速度。

  • sourceMap ,将错误消息位置映射到模块(储存着位置信息)。

  • drop_console ,打包时剔除所有的  console 语句

  • drop_debugger ,打包时剔除所有的  debugger 语句

作为一个管小组前端的懒B,很多时候写页面会遗留 console.log ,影响性能。设置个  drop_console 就非常香。以下配置亲测有效。

更多的配置请看Terser Plugin

6.2 双端开启 gzip

开启gzip压缩的好处是什么?

可以减小文件体积,传输速度更快。gzip是节省带宽和加快站点速度的有效方法。

  • 服务端发送数据时可以配置 Content-Encoding:gzip,用户说明数据的压缩方式

  • 客户端接受到数据后去检查对应字段的信息,就可以根据相应的格式去解码。

  • 客户端请求时,可以用 Accept-Encoding:gzip,用户说明接受哪些压缩方法。

6.2.1 Webpack 开启  gzip

这里使用的插件为: CompressionWebpackPlugin

具体配置:


开启gzip前


开启gzip后

gzip后的大小从277KB到只有~91.2KB!

6.2.2 扩展知识: Nginx 的  gzip 设置

打开 /etc/nginx/conf.d 编写以下配置。

Nginx 尝试查找并发送文件  /path/to/bundle.js.gz 。如果该文件不存在,或者客户端不支持  gzip ,Nginx则会发送该文件的未压缩版本。

保存配置后,重新启动 Nginx :


开启gzip前


开启gzip后

6.2.3 如何验证 gzip

通过使用 curl 测试每个资源的请求响应,并检查  Content-Encoding

显示 Content-Encoding:gzip ,即为 配置成功

求一份深圳的内推

目前本人在(又)准备跳槽,希望各位大佬和HR小姐姐可以内推一份靠谱的深圳前端岗位! 996.ICU 就算了。

  • 微信:  huab119

  • 邮箱:  454274033@qq.com

作者掘金文章总集

  • 「从源码中学习」面试官都不知道的Vue题目答案

  • 「从源码中学习」Vue源码中的JS骚操作

  • 「从源码中学习」彻底理解Vue选项Props

  • 「Vue实践」项目升级vue-cli3的正确姿势

  • 为何你始终理解不了JavaScript作用域链?

公众号