rrweb 是使用typescript 開發的web 操做錄製以及回放框架,包含了比較完整的系統組件css
- rrweb-snapshot 進行dom 與操做實踐的關聯處理
- rrweb 主要包含了
record
以及replay
- rrweb-player rrweb 的UI 提供了方便的基於UI的操做,好比暫停,時間段選擇
簡單使用
使用docker-compose 運行,同時使用openresty提供了一個簡單的rest api(就是request 以及response沒有具體的存儲操做)html
- 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 文件nginx
-- 很簡單就是獲取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 頁面
代碼很簡單,就是點擊git
<!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 class="some-title">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 id="replaycontent">
</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
- 效果
說明
從目前的使用上還有莫名有一個奇怪的bug,可是仍是一個不錯的開源方案,很值得學習使用下github
參考資料
https://github.com/rrweb-io/rrweb
https://www.rrweb.io/
https://github.com/rongfengliang/rrweb-basic-learningweb