自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

前端如何靜悄悄錄制用戶的操作過(guò)程,靜悄悄上傳到服務(wù)器

開(kāi)發(fā) 項(xiàng)目管理
公司有很多的項(xiàng)目,但是并不是每一個(gè)項(xiàng)目都很重要,其實(shí)重要的項(xiàng)目就那么幾個(gè),上面也是很重視這幾個(gè)項(xiàng)目,尤其是對(duì)一些生產(chǎn)問(wèn)題的關(guān)注度很高。

背景

公司有很多的項(xiàng)目,但是并不是每一個(gè)項(xiàng)目都很重要,其實(shí)重要的項(xiàng)目就那么幾個(gè),上面也是很重視這幾個(gè)項(xiàng)目,尤其是對(duì)一些生產(chǎn)問(wèn)題的關(guān)注度很高。

這幾天上面交代下來(lái)了,需要對(duì)這些項(xiàng)目做一些用戶行為的記錄,主要是為了更好地還原用戶在某一個(gè)時(shí)間點(diǎn)的操作過(guò)程

圖片

注意點(diǎn)

想要完成這個(gè)需求,仔細(xì)想了一下,需要注意幾個(gè)點(diǎn):

  • 跨框架使用:這些項(xiàng)目有vue、angular、react,需要都能適用
  • 能錄制用戶行為:能把用戶在頁(yè)面上的操作錄制下來(lái)
  • 能回放錄制:如果不能回放,那么這個(gè)錄制就無(wú)意義了
  • 用戶無(wú)感知:必須做到用戶無(wú)感知才行

思考 & 技術(shù)方案

說(shuō)到前端視頻的錄制,我們會(huì)想到 webRTC 這個(gè)技術(shù),他能做到錄制屏幕的效果,但是通過(guò) webRTC 去完成這個(gè)方案的話,有幾個(gè)缺點(diǎn):

  • 做不到用戶無(wú)感知,需要用戶同意才能錄制
  • 錄制的視頻太大了,太占內(nèi)存了
  • 學(xué)習(xí)成本比較高,這也是原因之一

那怎么才能做到:

  • 用戶無(wú)感知
  • 不錄制視頻

其實(shí)只要不錄制視頻了,那么用戶肯定就無(wú)感知,因?yàn)橐坏┮浺曨l,瀏覽器肯定要詢問(wèn)用戶同意不同意。

所以我們選擇了另一個(gè)方案 rrweb,一個(gè)用來(lái)錄制用戶頁(yè)面行為的庫(kù)~

rrweb

rrweb 是 record and replay the web 的簡(jiǎn)寫,旨在利用現(xiàn)代瀏覽器所提供的強(qiáng)大 API 錄制并回放任意 web 界面中的用戶操作。

效果展示

圖片

基本使用

我們先定義好 html 結(jié)構(gòu),三個(gè)按鈕

  • 錄制:點(diǎn)擊開(kāi)始錄制
  • 回放:點(diǎn)擊開(kāi)始回放
  • 返回:點(diǎn)擊重新再來(lái)

還有一個(gè) replayer ,用來(lái)當(dāng)做回放的容器

<template>
  <div class="main">
    <div >
      <el-button @click="record">錄制</el-button>
      <el-button @click="replay">回放</el-button>
      <el-button @click="reset">返回</el-button>
    </div>
    <div v-if="!showReplay">
      <div>
        <el-input style="width: 300px" v-model="value" />
      </div>
      <div>
        <el-button>按鈕1</el-button>
      </div>
      <div>
        <el-button>按鈕2</el-button>
      </div>
      <div>
        <el-button>按鈕3</el-button>
      </div>
    </div>
    <div ref="replayer"></div>
  </div>
</template>

我們需要先安裝兩個(gè)包:npm i rrweb rrwebPlayer

  • rrweb:用來(lái)錄制網(wǎng)頁(yè)的
  • rrwebPlayer:用來(lái)回放的

rrweb擁有一個(gè) record 函數(shù)來(lái)進(jìn)行錄制操作,并可傳入配置,emit屬性就是用戶操作的監(jiān)聽(tīng)函數(shù),接收一個(gè)參數(shù)event,這個(gè)參數(shù)是什么,我們后面會(huì)說(shuō)~

然后我們定義三個(gè)函數(shù):

  • record:錄制函數(shù)
  • replay:回放函數(shù)
  • reset:返回/重置函數(shù)
const rrweb = require("rrweb");
import rrwebPlayer from "rrweb-player";

const events = ref([]);
const stopFn = ref(null);
const showReplay = ref(false);
const replayer = ref(null)

const record = () => {
  console.log("開(kāi)始錄制");
  stopFn.value = rrweb.record({
    emit: (event) => {
      events.value.push(event);
    },
    // 支持錄制canvas
    recordCanvas: true,
    collectFonts: true,
  });
};
const replay = () => {
  stopFn.value();
  showReplay.value = true;
  new rrwebPlayer({
    // 可以自定義 DOM 元素
    target: replayer.value,
    // 配置項(xiàng)
    props: {
      // 傳入events
      events: events.value,
    },
  });
};
const reset = () => {
  showReplay.value = false;
  events.value = []
};

錄的是視頻嗎?

我們之前說(shuō)了:一旦要錄視頻,瀏覽器肯定要詢問(wèn)用戶同意不同意。但是我們發(fā)現(xiàn)我們使用 rrweb 去錄制,瀏覽器并沒(méi)有詢問(wèn),做到了無(wú)感知~所以我們可以推斷出,rrweb 錄制的并不是視頻,那錄制的是什么呢?

我們其實(shí)可以試著去輸出一下剛剛的參數(shù) event 看看是什么

rrweb.record({
    emit: (event) => {
        // 輸出
+      console.log(event)
      events.value.push(event);
    },
});

圖片

我們可以看到這個(gè)event記錄的東西是當(dāng)前頁(yè)面的DOM結(jié)構(gòu),當(dāng)用戶操作頁(yè)面時(shí),rrweb會(huì)將每一次的DOM結(jié)構(gòu)轉(zhuǎn)換成對(duì)象形式,通過(guò) emit 函數(shù)的第一個(gè)參數(shù)輸出,我們使用一個(gè)數(shù)組去記錄這一次次的DOM結(jié)構(gòu),然后把它傳給rrweb-player,它能將這些DOM結(jié)構(gòu)按照先后順序,一個(gè)一個(gè)展示出來(lái),自然就相當(dāng)于是視頻的展示效果了~

圖片

rrweb能記錄這些頁(yè)面的 DOM 行為:

  • 節(jié)點(diǎn)創(chuàng)建、銷毀
  • 節(jié)點(diǎn)屬性變化
  • 文本變化
  • 鼠標(biāo)移動(dòng)
  • 鼠標(biāo)交互
  • 頁(yè)面或元素滾動(dòng)
  • 視窗大小改變
  • 輸入

上傳 & 優(yōu)化

我們記錄的這些數(shù)據(jù),需要上傳到后端那邊去,方便后續(xù)在后臺(tái)管理系統(tǒng)里管理這些回放~

很多人會(huì)說(shuō)這樣一直錄制,那豈不是數(shù)據(jù)量很大?所以我覺(jué)得只有在一些重要的頁(yè)面,才需要做錄制行為的操作,而不是每一個(gè)頁(yè)面都去做這樣的操作~

并且每次上傳需要一定的時(shí)間間隔,不能上傳太頻繁,不然瀏覽器壓力會(huì)增大~

const record = () => {
  console.log("開(kāi)始錄制");
  stopFn.value = rrweb.record({
    emit: (event) => {
      events.value.push(event);
    },
    recordCanvas: true,
    collectFonts: true,
  });
};

const report = async () => {
  await reportRequest(events.value);
  events.value = [];
}

// 20s 去上傳一次
setInterval(report, 10 * 2000);

同時(shí),雖然現(xiàn)在上傳的是DOM結(jié)構(gòu)的對(duì)象,大小遠(yuǎn)遠(yuǎn)比視頻小,但是其實(shí)還是不小的

圖片

所以我們需要采取措施,去壓縮一下數(shù)據(jù),壓縮后再進(jìn)行上傳,這樣能降低服務(wù)器的壓力~我們可以使用packFn屬性來(lái)對(duì)錄制的數(shù)據(jù)進(jìn)行壓縮,同時(shí)回放時(shí)也要用unpackFn去解碼

const record = () => {
  console.log("開(kāi)始錄制");
  stopFn.value = rrweb.record({
    emit: (event) => {
      events.value.push(event);
    },
    recordCanvas: true,
    collectFonts: true,
+    packFn: rrweb.pack
  });
};

const replay = () => {
  stopFn.value();
  showReplay.value = true;
  new rrwebPlayer({
    // 可以自定義 DOM 元素
    target: replayer.value,
    // 配置項(xiàng)
    props: {
      // 傳入events
      events: events.value,
+      unpackFn: rrweb.unpack,
    },
  });
};

圖片

責(zé)任編輯:武曉燕 來(lái)源: 前端之神
相關(guān)推薦

2012-05-14 11:01:50

搜索引擎微軟

2013-08-14 10:03:56

微信支付

2024-09-09 11:14:31

降噪技術(shù)AR技術(shù)VR

2009-12-11 17:29:22

Linux桌面

2011-02-24 14:23:18

2009-12-29 10:44:19

2009-08-25 15:48:03

C#數(shù)組操作

2010-01-06 11:30:22

.NET Framew

2014-07-22 10:36:52

惡意程序小米手機(jī)

2010-05-27 15:11:44

MySQL保存

2010-05-17 13:28:15

MySQL 復(fù)制

2015-06-19 14:07:53

免費(fèi)WiFi北京

2010-03-30 12:50:42

Oracle存儲(chǔ)

2010-04-26 00:42:08

DNS負(fù)載均衡

2009-01-15 09:25:00

2010-06-30 12:39:11

2009-12-16 17:11:10

Fedora 掛載

2010-04-14 13:18:53

安裝無(wú)線適配器

2025-03-24 07:15:00

WebWorkerWeb瀏覽器

2019-01-09 09:52:30

互聯(lián)網(wǎng)馬云馬化騰
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)