尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Puppeteer 无头屏幕配置实战:--screen-info 静态多屏与 addScreen 动态屏幕管理

Puppeteer 无头屏幕配置实战:--screen-info 静态多屏与 addScreen 动态屏幕管理 Puppeteer 无头屏幕配置实战--screen-info 静态多屏与 addScreen 动态屏幕管理【免费下载链接】puppeteerJavaScript API for Chrome and Firefox项目地址: https://gitcode.com/GitHub_Trending/puppeteer1/puppeteer本指南以 Puppeteer 官方文档 screen-configuration.md 为骨架系统讲解如何让无头headlessChrome 使用真实的多显示器屏幕拓扑既可通过启动参数--screen-info在浏览器启动前一次性描述多个屏幕及其位置、尺寸、方向与标签也可以在浏览器运行期间通过Browser.addScreen/Browser.removeScreen动态增删屏幕并用Browser.screens随时读取当前屏幕集合。读完本文你将掌握多屏无头环境下 Web 应用“跨屏布局、副屏窗口最大化、多屏渲染”等场景的测试与模拟方法。为什么需要为无头 Chrome 配置屏幕物理机上的浏览器窗口管理、screen.availWidth/availHeight等 Web API 都依赖操作系统提供的屏幕信息。而在 headless 模式下Chrome 没有真实物理屏幕默认只会模拟一块逻辑屏幕详见下文“无开关时的默认屏幕”。如果你的被测页面需要验证多屏布局、副屏弹出窗口位置、双屏拼接广告、竖屏适配等行为就必须先为无头浏览器构造出符合预期的“虚拟屏幕拓扑”。该能力在 Chromium 侧由 headless 组件中的screen_info实现支撑仓库文档原文注明了对应 Chromium 内部 README而在 Puppeteer 侧则暴露为两个层次的 API静态的--screen-info启动开关与动态的Browser.addScreen/removeScreen方法。使用 --screen-info 开关配置双屏启动环境--screen-info是一个传给 Chrome 的命令行开关用于在启动阶段配置 headless 屏幕。其字符串语法形如{800x600 label1st}{600x800 label2nd}——每个屏幕用一对花括号描述内部为宽度x高度可附带labelxxx命名。下面的脚本让 Chrome 运行在“双屏”环境主屏 800x600 横屏landscape副屏 600x800 竖屏portrait且副屏紧贴主屏右侧即副屏left偏移量等于主屏宽度 800import puppeteer from puppeteer-core; const browser await puppeteer.launch({ args: [--screen-info{800x600 label1st}{600x800 label2nd}], }); const screens await browser.screens(); const screenInfos screens.map( s Screen [${s.id}] ${s.left},${s.top} ${s.width}x${s.height} label${s.label} isPrimary${s.isPrimary} isExtended${s.isExtended} isInternal${s.isInternal} colorDepth${s.colorDepth} devicePixelRatio${s.devicePixelRatio} avail${s.availLeft},${s.availTop} ${s.availWidth}x${s.availHeight} orientation.type${s.orientation.type} orientation.angle${s.orientation.angle}, ); console.log(Number of screens: ${screens.length}\n screenInfos.join(\n)); await browser.close();运行输出Number of screens: 2 Screen [1] 0,0 800x600 label1st isPrimarytrue isExtendedtrue isInternalfalse colorDepth24 devicePixelRatio1 avail0,0 800x600 orientation.typelandscapePrimary orientation.angle0 Screen [2] 800,0 600x800 label2nd isPrimaryfalse isExtendedtrue isInternalfalse colorDepth24 devicePixelRatio1 avail800,0 600x800 orientation.typeportraitPrimary orientation.angle0注意输出中的两个关键推论第一个声明的屏幕自动成为主屏isPrimarytrue位于虚拟桌面左上角(0,0)第二个屏幕的left800说明它从主屏右边缘开始由此构成“主屏在左、副屏在右”的扩展桌面。方向orientation由宽高自动推导800x600宽大于高为landscapePrimary600x800高大于宽为portraitPrimary旋转角angle均为 0。这是与 ChromiumEmulation.getScreenInfos返回结果一致的行为见下文源码部分。各 ScreenInfo 字段语义browser.screens()返回的是ScreenInfo对象的数组。其完整结构定义于 api/Browser.ts字段含义如下字段类型含义idstring屏幕唯一标识示例输出中显示为[1]、[2]也是removeScreen需要的参数left/topnumber屏幕在虚拟桌面中的左上角坐标width/heightnumber屏幕逻辑分辨率availLeft/availTop/availWidth/availHeightnumber去掉任务栏/工作区留白后页面可用的工作区矩形devicePixelRationumber设备像素比示例中为 1colorDepthnumber色深示例中为 24orientationScreenOrientation方向对象含type如landscapePrimary/portraitPrimary与angle旋转角isExtendedboolean是否为扩展屏单屏时为 false多屏时为 trueisInternalboolean是否内建屏幕headless 模拟屏为 falseisPrimaryboolean是否主屏labelstring屏幕名称对应--screen-info中的label或addScreen传入的label接口本身的availWidth/availHeight/availLeft/availTop、colorDepth等均声明在 puppeteer.screeninfo.md 的 API 参考页中。无 --screen-info 开关时的默认屏幕如果不传--screen-infoheadless 默认只有一块800x600的屏幕但若同时指定了--window-size开关则 headless 屏幕会放大到请求的窗口尺寸。也就是说--screen-info是比--window-size更精细、能力更强的屏幕控制手段——前者描述的是“屏幕硬件拓扑”后者只影响单个窗口/视口大小。仓库的集成测试也印证了该用法在 page.test.ts 中Page.resize相关测试专门通过args: [--screen-info{3840x2160}]启动一个 4K 无头屏并配合page.setViewport(null)移除默认 800x600 视口对窗口尺寸的限制进而验证浏览器窗口可按页面内容尺寸自动调整。这说明要测试大屏或窗口自适应逻辑时先声明一块足够大的屏幕是必要前提。:::caution 使用前提--screen-info开关只在 headless 模式下生效。Headful有头Chrome 始终使用操作系统真实物理屏幕该开关会被忽略。 :::动态屏幕配置运行期 addScreen / removeScreen / screens除了启动时一次性声明外Puppeteer 还允许在 Chrome 运行期间动态调整屏幕集合Browser.screens()读取当前屏幕配置Browser.addScreen(params)新增一个屏幕并返回其ScreenInfoBrowser.removeScreen(screenId)移除一个屏幕。下面的脚本先以单屏启动随后动态添加一个位于右侧的 800x600 副屏再将其移除全程打印每一步的屏幕配置import puppeteer from puppeteer-core; const browser await puppeteer.launch({ args: [--screen-info{800x600 label1st}], }); function getScreenInfo(s) { return ( Screen [${s.id}] ${s.left},${s.top} ${s.width}x${s.height} label${s.label} isPrimary${s.isPrimary} isExtended${s.isExtended} ); } async function logScreenConfig(text) { if (text ! undefined) { console.log(text); } const screens await browser.screens(); const screenInfos screens.map(s getScreenInfo(s)); console.log( Number of screens: ${screens.length}\n screenInfos.join(\n), ); } await logScreenConfig(---- Initial:); // Add a screen. const addedScreenInfo await browser.addScreen({ left: 800, top: 0, width: 800, height: 600, label: 2nd, }); console.log(Added screen: getScreenInfo(addedScreenInfo)); await logScreenConfig(---- With the screen added:); // Remove the added screen. await browser.removeScreen(addedScreenInfo.id); await logScreenConfig(---- With added screen removed:); await browser.close();对应输出---- Initial: Number of screens: 1 Screen [1] 0,0 800x600 label1st isPrimarytrue isExtendedfalse Added screen: Screen [2] 800,0 800x600 label2nd isPrimaryfalse isExtendedtrue ---- With the screen added: Number of screens: 2 Screen [1] 0,0 800x600 label1st isPrimarytrue isExtendedtrue Screen [2] 800,0 800x600 label2nd isPrimaryfalse isExtendedtrue ---- With added screen removed: Number of screens: 1 Screen [1] 0,0 800x600 label1st isPrimarytrue isExtendedfalse输出清晰展示了isExtended的语义变化单屏时主屏isExtendedfalse一旦存在第二块屏幕两块屏的isExtended都变为true移除副屏后回到初始状态。AddScreenParams动态新增屏幕可控制哪些属性addScreen的参数类型AddScreenParams定义在 api/Browser.ts除必需的几何位置外还支持若干可选属性参数类型是否必填说明left/topnumber必填新屏幕在虚拟桌面中的左上角坐标width/heightnumber必填新屏幕的分辨率workAreaInsetsWorkAreaInsets可选工作区四周留白{top, left, bottom, right}用于模拟任务栏等占据的区域devicePixelRationumber可选设备像素比rotationnumber可选屏幕旋转角度会反映到orientation.anglecolorDepthnumber可选色深labelstring可选屏幕标签isInternalboolean可选是否标记为内建屏其中workAreaInsets对页面可感知尺寸影响很大可用工作区availWidth/availHeight 屏幕width/height减去对应方向的 insets。仓库测试 browser.test.ts 便验证了这一关系——向addScreen传入width: 1600, height: 1200, workAreaInsets: {bottom: 80}后断言返回结果满足availHeight: 1120即1200 - 80、availWidth: 1600、colorDepth: 32、devicePixelRatio: 1、orientation: {angle: 0, type: landscapePrimary}等同时isPrimary: false、isExtended: true、id为任意字符串。这说明 addScreen 返回的对象就是 Chrome 内部屏幕状态的真实回显。动态副屏的实际用途动态副屏最常见的价值是配合窗口管理 API 使用可以在副屏上打开窗口并执行最大化。同样在 browser.test.ts 的测试中先addScreen添加一个 1600x1200 副屏再通过context.newPage({type: window, windowBounds: ...})在副屏avail区域内开窗随后用browser.setWindowBounds(windowId, {windowState: maximized})将该窗口最大化到副屏。这组测试证明多屏无头环境完全支持“在不同屏幕上创建并最大化窗口”的桌面类应用行为验证。:::caution 使用前提Browser.addScreen与Browser.removeScreen仅在 headless 模式下可用Browser.screens则在 headful 与 headless 两种模式下均可调用。此外从 api/Browser.ts 中removeScreen的源码注释可知移除主屏primary screen会失败——至少保留一块主屏是屏幕拓扑的不变约束。 :::源码实现从 Puppeteer API 到 Chromium 命令从仓库源码结构看这三组屏幕 API 是一套典型的“协议无关抽象 协议实现”体系协议无关的抽象层在 api/Browser.ts 中Browser基类将screens()、addScreen(params)、removeScreen(screenId)声明为抽象方法并同步导出ScreenInfo、ScreenOrientation、AddScreenParams、WorkAreaInsets等公开类型。CDPChrome DevTools Protocol实现在 cdp/Browser.ts 中三者被映射为三条Emulation域命令screens()→Emulation.getScreenInfosaddScreen(params)→Emulation.addScreenparams 原样透传removeScreen(screenId)→Emulation.removeScreenWebDriver BiDi 协议下的限制在 bidi/Browser.ts 中三个方法目前直接抛出UnsupportedOperation。可以推断通过 WebDriver BiDi 协议连接的 Firefox/浏览器暂不支持这套屏幕模拟 API当前仅 CDP 通道Chromium headless具备完整能力。也就是说--screen-info与addScreen/removeScreen最终都收敛到 Chromium 的 headless 屏幕模拟能力Puppeteer 只是把 CDP 命令包装成了类型安全的 TypeScript 方法并在运行时经由browser.screens()与页面内window.screen/screen.avail*等 Web API 保持一致。小结与使用建议启动前已知拓扑用--screen-info语法为连续花括号块每块{宽x高 label名称}先声明者为主屏方向由宽高比自动推导屏幕按left/top拼接成虚拟桌面。运行期变化用Browser.addScreen/Browser.removeScreen适合在同一个浏览器会话中先后模拟“单屏→双屏→单屏”等切换场景其中workAreaInsets可用于精细模拟任务栏对avail*的影响。读取现状统一用Browser.screens()其返回字段与Emulation.getScreenInfos的产出一一对应可同时用于 headful 与 headless。协议注意上述屏幕 API 的完整实现位于 CDP 通道经 WebDriver BiDi 连接时 addScreen/removeScreen/screens 均不可用。且一切屏幕模拟都发生在 headless 模式内headful 模式始终走真实物理屏幕。与视口/窗口的关系默认无头屏为 800x600--window-size可放大之若配合--screen-info声明大屏后仍受 800x600 默认视口限制可参照 page.test.ts 的做法先page.setViewport(null)解除视口约束再测试窗口级行为。如需进一步查阅类型细节可参考 puppeteer.addscreenparams.md、puppeteer.screeninfo.md、puppeteer.browser.addscreen.md 与 puppeteer.browser.removescreen.md 等 API 文档。【免费下载链接】puppeteerJavaScript API for Chrome and Firefox项目地址: https://gitcode.com/GitHub_Trending/puppeteer1/puppeteer创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表