58 lines
2.0 KiB
JavaScript
58 lines
2.0 KiB
JavaScript
/**
|
||
* CDP 截屏小工具:连接正在运行的 Electron/Chromium 远程调试端口,截取页面渲染结果
|
||
* 用途:打包后无头验证渲染层 UI(登录页 logo、页面是否白屏等),无需人工肉眼确认
|
||
* 用法:node scripts/cdp-screenshot.mjs <debug端口> <输出png路径>
|
||
* 依赖:Node 22+(内置全局 WebSocket),无需安装任何包
|
||
*/
|
||
import { writeFileSync } from 'node:fs'
|
||
|
||
const port = process.argv[2] || '9223'
|
||
const outFile = process.argv[3] || 'screenshot.png'
|
||
|
||
// 从调试端口拿到页面目标的 WebSocket 调试地址
|
||
const targets = await (await fetch(`http://127.0.0.1:${port}/json/list`)).json()
|
||
const page = targets.find((t) => t.type === 'page')
|
||
if (!page) {
|
||
console.error('未找到 page 类型的调试目标')
|
||
process.exit(1)
|
||
}
|
||
|
||
const ws = new WebSocket(page.webSocketDebuggerUrl)
|
||
let msgId = 0
|
||
/** 发送 CDP 命令并等待对应 id 的响应 */
|
||
function send(method, params = {}) {
|
||
const id = ++msgId
|
||
return new Promise((resolve, reject) => {
|
||
const onMessage = (event) => {
|
||
const data = JSON.parse(event.data)
|
||
if (data.id === id) {
|
||
ws.removeEventListener('message', onMessage)
|
||
data.error ? reject(new Error(data.error.message)) : resolve(data.result)
|
||
}
|
||
}
|
||
ws.addEventListener('message', onMessage)
|
||
ws.send(JSON.stringify({ id, method, params }))
|
||
})
|
||
}
|
||
|
||
ws.addEventListener('open', async () => {
|
||
try {
|
||
// 等一帧渲染稳定后截屏
|
||
await send('Page.enable')
|
||
const { data } = await send('Page.captureScreenshot', { format: 'png' })
|
||
writeFileSync(outFile, Buffer.from(data, 'base64'))
|
||
console.log(`截图已保存: ${outFile}`)
|
||
// 顺带收集页面控制台报错,辅助排查
|
||
const { result } = await send('Runtime.evaluate', {
|
||
expression: 'document.title + " | " + location.hash',
|
||
returnByValue: true,
|
||
})
|
||
console.log(`页面状态: ${result.value}`)
|
||
} catch (err) {
|
||
console.error('CDP 操作失败:', err.message)
|
||
process.exitCode = 1
|
||
} finally {
|
||
ws.close()
|
||
}
|
||
})
|