天天看點

使用rrweb 進行web 操作錄制以及回放

使用rrweb 進行web 操作錄制以及回放

rrweb 是使用typescript 開發的web 操作錄制以及回放架構,包含了比較完整的系統元件

  • rrweb-snapshot 進行dom 與操作實踐的關聯處理
  • rrweb 主要包含了record 以及replay
  • rrweb-player rrweb 的UI 提供了友善的基于UI的操作,比如暫停,時間段選擇

簡單使用

使用docker-compose 運作,同時使用openresty提供了一個簡單的rest api(就是request 以及response沒有具體的存儲操作)
  • docker-compose 檔案
version: "3"      
services:       
app:       
image: openresty/openresty:alpine-fat      
ports:      
- "8080:8080"      
volumes:      
- "./nginx_lua/:/opt/app/"      
- "./index.html:/usr/local/openresty/nginx/html/index.html"      
- "./nginx.conf:/usr/local/openresty/nginx/conf/nginx.conf"      
  • nginx.conf 配置
worker_processes 1;      
user root;      
events {      
worker_connections 1024;      
}      
http {      
include mime.types;      
default_type application/octet-stream;      
sendfile on;      
keepalive_timeout 65;      
root html;      
gzip on;      
lua_package_path '/opt/app/?.lua;;';      
lua_code_cache off;      
lua_need_request_body on;      
real_ip_header X-Forwarded-For;      
real_ip_recursive on;      
server {      
listen 8080;      
server_name localhost;      
charset utf-8;      
ssi on;      
default_type text/html;      
location / {      
index index.html index.html;      
}      
location /api {      
content_by_lua_block {      
require("api/api")()      
}      
}      
error_page 500 502 503 504 /50x.html;      
location = /50x.html {      
root html;      
}      
}      
}      
  • 基于openresty 的簡單api
    nginx_lua/api/api.lua 檔案
--  很簡單就是擷取request body,後邊的處理就可以有好多方法了      
local json = require("cjson")      
function init()      
ngx.req.read_body()      
local body = ngx.req.get_body_data()      
if not body then      
if ngx.req.get_body_file() then      
return nil, "request body did not fit into client body buffer, consider raising 'client_body_buffer_size'"      
else      
return ""      
end      
end      
local res = {      
code = 1,      
message ="ok"      
}      
ngx.log(ngx.ERR, body)      
ngx.say(json.encode(res))      
end      
return init      
  • 內建rrweb 的index.html 頁面
    代碼很簡單,就是點選
<!DOCTYPE html>      
<html lang="en">      
<head>      
<meta charset="UTF-8" />      
<meta name="viewport" content="width=device-width, initial-scale=1.0" />      
<meta http-equiv="X-UA-Compatible" content="ie=edge" />      
<title>rrweb demo web site</title>      
<script crossorigin="anonymous" src="https://cdn.jsdelivr.net/npm/rrweb@latest/dist/rrweb.min.js"></script>      
<script crossorigin="anonymous" src="https://cdn.jsdelivr.net/npm/rrweb@latest/dist/record/rrweb-record.min.js"></script>      
<link rel="stylesheet" crossorigin="anonymous"      
href="https://cdn.jsdelivr.net/npm/rrweb-player@latest/dist/style.css" />      
<script crossorigin="anonymous" src="https://cdn.jsdelivr.net/npm/rrweb-player@latest/dist/index.js"></script>      
</head>      
<body>      
<h1 >this is some title for test</h1>      
<input type="button" value="record action" onclick="record()" />      
<br />      
<input type="button" value="replay action" onclick="replay()" />      
<div >      
</div>      
<script>      
window.events = [];      
function record() {      
rrweb.record({      
emit(event) {      
// 将 event 存入 events 數組中      
events.push(event);      
},      
});      
}      
function replay() {      
new rrwebPlayer({      
target: document.getElementById("replaycontent"), // 可以自定義 DOM 元素      
data: {      
events,      
},      
});      
}      
// save 函數用于将 events 發送至後端存入,并重置 events 數組      
function save() {      
const body = JSON.stringify(window.events);      
events = [];      
fetch("http://localhost:8080/api", {      
method: "POST",      
headers: {      
"Content-Type": "application/json",      
},      
body,      
});      
}      
// 每 10 秒調用一次 save 方法,避免請求過多      
setInterval(save, 10 * 1000);      
</script>      
</body>      
</html>      

啟動&&試用

  • 啟動
docker-compose up -d      
  • 效果
使用rrweb 進行web 操作錄制以及回放

說明

參考資料

繼續閱讀