使用 rrweb 录制和回放用户交互操作

一直以来项目的日志功能只记录了用户的登录和接口请求操作日志,用来辅助我们定位和解决反馈的异常问题。这些日志大多数情况下并不会记录用户是如进行操作的,只记录发起请求时携带的参数信息。大多数情况下这些日志已经足够帮助我们发现和解决问题了。
但在一些非常独特的问题反馈中,我们没有办法了解到用户是如何触发这些异常请求的。还需要去主动联系用户询问当时的操作场步骤去复现,或者按照日志中的参数去猜测用户是如何操作的。

最近正在听 Web Worker 这档播客节目,有一期节目邀请到了 Aryu 大佬,就发现了 rrweb 这个项目。有兴趣的话可以从项目的主页中在线尝试录制和回放功能,预设了3个业务场景的录制体验Demo。

可以看到录制效果非常不错。能录制到鼠标轨迹、滚轮操作、各种元素的聚焦、下拉和光标位置等各种各样的操作记录。

  • 但因为是DOM级别的录制,所以浏览器原生提供的功能,并不会被录制到。比如说 <select> 元素提供的下拉操作和 <input type="file"> 提供的文件选择操作。
  • v1.0.0 开始以插件的形式增加了控制台录制的功能。

而且使用起来非常简单,只需要引入和执行 record 方法就可以启动录制了,然后按照自己的需求去存储即可。

import { record } from 'rrweb'

let events = [];
record({
  emit(event) {
    // 将用户操作的 event 存入 events 数组中
    events.push(event);
  },
});
阅读全文

VueUse 中的 useTimeAgo 函数的国际化和浏览器内置国际化API

看到一个帖子提到了 VueUse 中的一个函数 useTimeAgo,比较好奇这个函数是干什么的就点开了帖子看了一下。
其实就是一个相对时间对比的函数,输入一个目标时间(允许时间戳或者格式化日期字符串),返回目标距离现在的文本内容。

举个例子:

import { useTimeAgo } from '@vueuse/core'

useTimeAgo(new Date()) // just now
useTimeAgo(new Date('2024-06-01')) // 2 weeks ago

但是 useTimeAgo 函数返回的文本内容是固定的英文字符串。所以,如果在中文环境下使用就可能会被挑战说需要展示中文的相对时间文本。
🔗 vueuse/packages/core/useTimeAgo/index.ts at main · vueuse/vueuse

看了一下 useTimeAgo 的实现,是支持自己做一份国际化配置,然后传入给 useTimeAgo 方法来使用的。

阅读全文

在 pikaz-excel-js 中设置单元格样式

pikaz-excel-js 是项目中已经使用的 Excel 导入导出库。简单的配置一下表头、表格数据就可以完成表格的导出操作了,使用起来非常简单。文档也非常的简单明了,并且有提供简单的参考示例模板:

但是文档中关于单元格样式(cellStyle)的说明就有点 “太简单” 了 👇

参数 说明 类型 可选值 默认值
cellStyle 单元格样式,每个单元格对象配置具体参数查看下方单元格样式 object
cell 单元格名称,支持 excel 单元格名称与数字行列格式,如 'A3''3-1' string

其他属性与表格全局样式设置方式一致

如果没有阅读示例代码,直接跳到文档中的这部分查看配置项就会有点不知道如何书写。

阅读全文

国际化开发插件 i18n-Ally

i18n Ally

i18n Ally 这个插件,很早之前就从各种的 VS Code 插件分享贴中了解到,但是一直都没有好好利用起来。特别是我当前开发的项目是我自己魔改的一个国际化维护方式 i18n Ally 并不能很好的支持。
而我的一些个人项目,并不会使用到国际化。所以即使安装了这个插件已经有将近一年了,也没有使用起来。

这几天正巧要新增加一个语言到项目中,所以趁着这次机会就决定把插件使用起来。也可以做一次内部分享,方便一下同事。现在新增了很多国际化的需求,应该可以提供一些便利。

阅读全文

淘宝镜像老域名SSL证书已过期

最近社区和社群里面有好多小伙伴在说怎么 npm 用不了,安装不了依赖了。
一看报错信息:request to https://npm.taobao.org/xxx failed, reason: certificate has expired

😂 很明显就是 npm.taobao.org 的域名证书过期了,一看果然。已经在1月22日的时候过期了。

域名过期-浏览器截图

所以切换到的“”的域名上面就好了:

$ npm config set registry https://registry.npmmirror.com

也可以使用 NRM 来切换。

阅读全文

在 Chrome 中使用 DevTools 限制CPU性能

昨天刷到在思否遇到一个想要限制CPU性能的问题。在我的认知里对于 DevTools 的使用是没办法限制CPU性能的,认为只能够限制网络条件(也就是在 Network 面板中通过修改 throttling 设置来限制网络条件,也错误的把OP的截图当成了调整网络条件的设置了)。
所以会想着通过系统自带的”节电模式”之类的来实现性能限制,或者借助外部的软件来调整CPU、GPU、内存相关的功率来实现性能限制。

但是OP在傍晚自己找到了解决办法,我才知道原来 DevTools 也可以限制CPU的。

设置截图

阅读全文

HTTP缓存限制 和 Service Worker

一直以来只知道 HTTP Cache 是有缓存总量上限的,但是不知道对于单个文件的体积大小也是有限制的。

在这次接盘的3D可视化项目中就遇到了这个问题。因为模型文件体积比较大,在实际使用中经常会反馈说载入时间过长。所以在拿到服务器权限之后就改了一下 Nginx 的配置文件开启了静态资源的 HTTP cache,以为完事大吉就和一线说载入时间慢的问题解决好了。现在进入项目会使用本地缓存,在第一次载入的时候会慢一些,后面再次进入就会快很多了。

但是实际使用中反馈过来的时依旧会有很长的载入时间。以为是 Nginx 的配置项写错了,就又去确认了一下。确实是开启了缓存的,首页的各种静态资源也是会被缓存,但是等我进入到模型展示页的时候就发现问题了!
最外层展示的模型是可以被缓存的,但是操作数据下钻之后开始展示内部模型从 Network 面板中看到的 glb 模型文件不是每一个都会从 disk cache 读取,有一些模型依旧会发起请求。

面板截图

所以就想着浏览器是不是可以有配置项可以修改,但是并没有(可以通过给快捷方式添加启动命令来修改,但不可能要求所有设备都这样做)。所以只能想其他法子来解决这个问题,自然就找到了 Service Worker

阅读全文

绑定的 value 值和元素的 value 值

今天在刷思否的时候遇到这样的一个问题:

<template>
  <input type="text" :value="inputValue" @input="handleInput" />
</template>

<script setup>
import { ref } from 'vue'
const inputValue = ref('')
const handleInput = (e) => {
  const val = e.target.value
  const reg = /^\d*$/
  if (reg.test(val)) {
    inputValue.value = val
  } else {
    inputValue.value = ''
  }
}
</script>

题主希望通过正则校验去限制输入框只能输入数字类型的值,但是只有在先输入数字再输入非数字的情况下才会被正确置空。如果一开始就是输入非数字的内容,后续即使继续输入非数字内容,输入框中的内容并不会清空。

我们可以在 Vue SFC Playground 中体验这个现象。

阅读全文

为什么v-model绑定的对象属性不是总是响应式?

v-model 仅仅只是 v-bind:value="value"@input="value = $event.target.value" 的语法糖吗?

一直以来我都喜欢在Vue中声明对象变量的时候给变量赋值一个空对象,而不是把所有的属性值一起声明好。
比如说:

// vue2.x form demo
export default {
  data() {
    return {
      // 我喜欢这样声明
      formData: {},
      // 而不是这样在声明时把所有的属性一起书写好 
      formData: {
        username: '',
        password: ''
      }
    }
  }
}

也可以从我之前关于 props 属性的笔记中察觉到 👉 Vue中接收没有声明的Prop属性[null/undefined]的接收问题

因为我在写业务的时候如果 props 的属性值不存在,传入的会是一个 undefined 而不是 null 或者 '' 这样的预设。因为我期望使用组件 props 中声明的默认值,而不是在外部预设的空值
所以一直以来我都在和小伙伴交流的时候也是推荐直接给变量一个空对象即可,除了一些数组属性需要单独声明。

但前段时间一位小伙伴向我提问:他在组件生命周期函数中给表单属性赋值了一个预设值,后续再使用 v-model 对表单属性修改时发现丢失了响应……

阅读全文

记一次旁观他人的技术面试

最近没有什么面试经历,上一次面试已经是将近一年前了,所以没办法有效回忆到当时面试的状况。好在近期肉大(@meathill)有在做一个模拟面试的选题,就可以另辟蹊径写一篇旁观其他人面试的文章。

奥利奥同学 是一位能力非常强的前端开发者。最开始了解到他是他在群里分享了自己使用 ThreeJS 开发的一个可交互3D汽车展厅项目 的开发经历,非常吸引眼球并且完成了配套的讲解教程,可以说是非常用心和细致的一个开发者了。

所以这一次我们就来旁观他的一次模拟面试,🏃‍🏃‍🏃‍

阅读全文