SuperAPI AI Directory

init-playwright

Testing & quality

View repository

Updated 10-16 07:23

About this skill

Initialize the Playwright toolchain in a pnpm monorepo

This skill documents the complete workflow for initializing the Playwright trio in a Vue 3 + Vite + TypeScript pnpm monorepo, along with 2 key environment pitfalls discovered during execution.

Applicable scenarios

  • First-time Playwright integration in a pnpm monorepo project
  • Large-screen/visualization projects that need visual regression testing
  • Need to equip AI agents with browser-driving capabilities (MCP + CLI skills)
  • Node 22 + Windows environment (pitfalls are related to Node version/OS)

⚠️ Headless browser CPU risk notice (important)

headless is not the same as lightweight. Headless Chromium still runs the full browser engine (Blink layout, V8 JS execution, WebGL/WebGPU rendering pipeline), it just does not display a window. In large-screen 3D/visualization projects , the CPU/GPU consumption of headless mode is almost identical to headed mode:

Scenario Risk level Description
pw_core MCP persistent connection 🔴 High The browser under MCP is along-lived process, it stays alive throughout the AI session and is not destroyed after use. Multiple Agents repeatedly invoking it → process stays resident → memory leak → CPU 100%
Large-screen 3D page repeatedly rendering 🔴 High ECharts WebGL/3D charts still fully execute the GPU rendering pipeline in headless mode. Every screenshot/snapshot triggers a repaint
pw_core + pw_visual running simultaneously 🟠 Medium-high Two Chromium processes in parallel, each using 200-500MB of memory; large-screen projects may spike to 1GB+
One-off CI testing 🟢 Low The process exits automatically after testing is complete, risk is controllable

Therefore, projects initialized with this skill must read and follow the constraints in the "Safe Use Guidelines for Headless Browsers" section. Especially on large-screen/visualization/3D-intensive projects, prioritize using pw_visual (headed) to drive the browser, and avoid letting pw_core (headless) stay resident for long periods.

Workflow overview

装三件套 → 端口固定 → 写根级 playwright.config.ts
    → visual-stability.css → .mcp.json + MCP 配置
    → playwright-cli + AI skills 生成
    → package.json scripts (test:e2e + ci)
    → e2e 冒烟测试 → 视觉基线测试
    → AI 记忆三处更新 → 验收

Step 1: Install the trio

pnpm add -D -w @playwright/test @playwright/cli playwright-mcp
pnpm exec playwright install chromium
pnpm exec playwright --version  # 验证

Responsibilities of the trio:

Package Purpose When to use
@playwright/test Write and run e2e/visual tests CI stabilization,pnpm test:e2e
@playwright/cli Generate skills for AI agents playwright-cli install --skills
playwright-mcp AI directly drives the browser via MCP pw_core (headless, saves tokens but high CPU), pw_visual (headed, visual reasoning)

Step 2: Fix the dev server port of the monorepo sub-app

For each app that needs testing, in vite.config.ts explicitly set the port to avoid playwright webServer port conflicts:

server: {
  port: 5174,          // 一期用 5173,二期用 5174,依此类推
  host: "127.0.0.1",   // 必须 127.0.0.1,不用 0.0.0.0
},

Step 3: Root-level playwright.config.ts

For monorepos, a single root config is recommended, using testDir + testMatch for centralized management, andprojects to distinguish different apps (for later expansion):

import { defineConfig, devices } from "@playwright/test";

const CI = !!process.env.CI;
const baseURL = "http://127.0.0.1:5174";

export default defineConfig({
	testDir: "./tests",
	testMatch: "**/*.spec.ts", // isolate from vitest *.test.ts
	outputDir: "artifacts/test-results",
	expect: {
		toHaveScreenshot: { maxDiffPixelRatio: 0.001 },
	},
	fullyParallel: false, // 大屏 3D 资源,并行争抢 GPU
	workers: 1,
	retries: CI ? 2 : 0,
	reporter: [["list"], ["html", { open: "never", outputFolder: "artifacts/playwright-report" }]],
	use: {
		baseURL,
		/** 显式声明 headless,不依赖默认值——确保 CI 和非 CI 行为一致 */
		headless: true,
		/** 禁用 GPU 及相关加速,降低 headless 模式下的 CPU 消耗 */
		launchOptions: {
			args: ["--disable-gpu", "--disable-software-rasterizer", "--disable-dev-shm-usage", "--no-sandbox"],
		},
		timezoneId: "Asia/Shanghai", // 中国大屏用上海时区
		viewport: { width: 1440, height: 900 },
		stylePath: "tests/visual/visual-stability.css",
		screenshot: "only-on-failure",
		trace: "retain-on-failure",
	},
	snapshotPathTemplate: "tests/visual/__screenshots__/{testFilePath}/{arg}{ext}",
	projects: [{ name: "chromium-desktop", use: { ...devices["Desktop Chrome"] } }],
	webServer: {
		command: "pnpm --filter <pkg-name> dev", // 见坑 #2
		url: baseURL,
		reuseExistingServer: !CI,
		timeout: 120_000,
	},
});

Pitfall #1: lint-staged prettier --experimental-cli crashes on Node 22

Symptom:lint-staged.config.js in "*": "prettier --experimental-cli --write" triggers in a Node 22 sandbox environment WorkTankWorkerError: Terminated, blocking all git commits.

Root cause: prettier 3.8.1's --experimental-cli depends on the worktank worker pool, which is unstable in some Node 22 environments.

Fix:

// lint-staged.config.js
export default {
	/**
	 * 临时去掉 prettier 的 --experimental-cli 标志。
	 * prettier 3.8.1 的 --experimental-cli worktank worker
	 * 在 Node 22 沙箱崩溃,回退到普通 --write,待上游修复后恢复。
	 *
	 * 另加 --ignore-unknown:跳过无 parser 的文件(如 .gitignore)
	 */
	"*": "prettier --write --ignore-unknown",
};

Note:--ignore-unknown is very important—without it, .gitignore and other files without a parser will also be blocked from committing by prettier errors.

Pitfall #2: playwright webServer's pnpm filter swallows --host

Symptom:playwright.config.ts 's webServer.command is set to pnpm dev:<app> --host 127.0.0.1, and after webServer auto-starts it returns 404. In CI mode reuseExistingServer: false will fail directly.

Root cause:pnpm dev:<app> expands to pnpm --filter <pkg> dev, and the following --host 127.0.0.1 is swallowed by the pnpm filter and not passed to vite.

Fix: do not pass --host/--portin webServer.command; rely on the existing server configuration in vite.config.ts:

// playwright.config.ts
webServer: {
  // 不在命令行传 --host/--port,依赖 vite.config.ts 的 server 配置
  command: "pnpm --filter <pkg> dev",
  url: baseURL,
  reuseExistingServer: !CI,
  timeout: 120_000,
},

General principle:For a vite project's playwright webServer, put all server parameters in vite.config.ts, and only pass dev。

Step 4: Isolate vitest and playwright naming

Test type File suffix Directory Who runs it
Unit/component/composable *.test.ts **/tests/ vitest (pnpm test)
e2e/page integration *.e2e.spec.ts tests/e2e/ playwright (pnpm test:e2e)
Visual regression *.visual.spec.ts tests/visual/ playwright (pnpm test:e2e)

The two configurations are naturally isolated (vitest include uses *.test.ts,playwright testMatch uses *.spec.ts), no need to exclude each other.

Step 5: Baseline screenshot commit strategy

  • Commit baseline screenshots to tests/visual/__screenshots__/(do not add to .gitignore)
  • Ignore artifacts/, test-results/, playwright-report/
  • First run --update-snapshots to generate baselines, second run pnpm test:e2e to verify

⚠️ Safe usage guidelines for headless browsers

Core principles

headless Chromium is not a lightweight mode, it runs a full browser engine in the background. The following guidelines help you use Playwright safely in your project and avoid CPU overload incidents.

① Prefer headed mode to drive the browser

Not all scenarios are suitable for headless. Choose by priority:

Recommended order Driving method Applicable scenarios Reason
✅ Most recommended pw_visual(headed) Daily driving by AI agent Visual effects are visible, saves CPU and won't "spin idle"
⚠️ As appropriate pw_core(headless) Token-sensitive, pure data verification Saves tokens but not CPU, under large-screen 3D the CPU consumption is almost the same as headed
✅ Recommended playwright test(CI) Automated testing, regression verification Short lifecycle, destroyed after use, risk is controllable

② MCP browser processes are persistent, their lifecycle must be managed

pw_core and pw_visual are mounted via the MCP protocol; after the AI agent starts, the browser process stays alive.It will not close automatically。

  • At the end of the session: the browser must be closed manually. Before the AI agent exits, execute:
    // 通过 pw_core 或 pw_visual 的 evaluate_script 关闭页面
    await page.close();
    // 或在测试脚本中使用 afterAll 钩子
    
  • Long periods of non-use: It is recommended to configure a process timeout or periodic restart in .mcp.json Configure process timeout or periodic restart
  • Monitor CPU: For large-screen projects, it is recommended to check Task Manager after the AI agent uses the browser to confirm that the Chromium process has exited

③ Special considerations for large-screen 3D projects

If your project includes ECharts WebGL/3D charts (such as Ring3DChart, 3D maps, etc.), CPU consumption in headless mode will be significantly higher than on pure 2D pages:

  • Do not take screenshots frequently: Each get-screenshot will trigger a complete WebGL frame render, causing CPU to spike to 100%
  • Use pw_visual > pw_core: headed mode at least lets you observe the browser's running status
  • Reduce meaningless page visits: The AI agent should avoid repeatedly "taking a look" at large-screen pages under headless
  • Consider lowering the screenshot resolution: Reduce the viewport or screenshot resolution in non-essential scenarios

④ Add a browser process reclamation reminder in agent-progress.md or AI memory

It is recommended to add the following constraint rules to the project's AI memory file:

### Playwright 浏览器进程使用规则(CPU 安全)

- AI 驱动浏览器默认使用 pw_visual(headed),仅 token 敏感场景用 pw_core
- 每次使用浏览器后检查任务管理器,确认 Chromium 进程已退出
- 禁止在 headless 模式下对 3D 大屏页面做高频截图(每 10 秒 1 次以上)
- 大屏 3D 页面优先用 pw_visual 驱动,避免无头模式下的 GPU 空转

⑤ Perform process cleanup at the end of the session

At the end of the AI session, it is recommended to run the following command to confirm that there are no residual Chromium processes:

# Windows - 检查遗留的 Chromium 进程
tasklist /FI "IMAGENAME eq chrome.exe" 2>NUL | find /I /N "chrome.exe"
# 可选:强制关闭残留(请先确认无其他用户进程)
# taskkill /F /IM chrome.exe 2>NUL
# Linux/macOS
# ps aux | grep -i chromium | grep -v grep
# killall chromium  # 谨慎使用

📋 Real incident retrospective: headless browser CPU overload

The following is a complete record of a real incident. This incident directly led to the complete removal of the Playwright toolchain from the project. It is recorded here to help future users identify the same type of risk.

Incident timeline

Time Event Status
Day 1 Playwright toolchain initialization completed: pw_core (headless) + pw_visual (headed) MCP, playwright.config.ts, e2e smoke tests, visual baselines, AI memory synchronized in three places ✅ All 12 acceptance items passed
Day 1→3 The AI agent repeatedly drove the headless browser through pw_core to perform screenshots/snapshots/page validation on large-screen 3D pages 🔄 Continuously running
Day 3 Host CPU spiked to 100%, and the system became noticeably laggy. Browser processes remained resident for a long time and did not exit 🔴 Severe
Day 3 The user decided to completely delete the Playwright toolchain, covering 17 items: MCP configuration, test code, configuration files, baseline screenshots, AI skill files, package.json dependencies, AI memory sections 🗑️ All cleared

Root cause analysis

初始化 Playwright(pw_core headless MCP)
  ↓ AI agent 在 3 天内反复通过 pw_core 驱动浏览器 "查看" 大屏 3D 页面
  ↓ headless Chromium 在后台完整执行 WebGL 渲染管线(3D 环形图、3D 地图等)
  ↓ 每次 get-screenshot / get-full-snapshot 都触发完整的 GPU 帧渲染
  ↓ MCP 协议下浏览器是长连接进程,不会用完即销毁
  ↓ 浏览器进程连续运行 3 天 → 内存持续增长 → CPU 100%
  ↓ 主机性能严重下降,用户被迫删除 Playwright

Key lessons

  1. The MCP browser is a long-lived connection, not a one-off call — it will remain alive throughout the entire AI session and will not close automatically after use. This is the biggest difference from pnpm test:e2e one-off tests.
  2. headless does not save CPU — what headless blocks is the window, not the rendering pipeline. In large-screen 3D projects, the GPU load under headless and headed is almost the same.
  3. An incident can be caused within 3 days — from initialization to complete deletion, the cycle was only 3 days. Once the AI agent starts calling the browser frequently, the CPU problem will rapidly worsen.
  4. The habitual "taking a look" is the most dangerous usage — AI agents are naturally inclined to take frequent screenshots/snapshots to confirm page status. In headless mode, this "taking a look" habit will trigger a large amount of useless GPU rendering.

Preventive measures

  • Confirm at initialization: Is your project a 3D large-screen type? If so, immediately switch to pw_visual (headed) instead of pw_core
  • Set rules before use: In AGENTS.md , explicitly constrain the frequency and manner of browser calls (refer to the safety rules in the "AI Memory Update Template")
  • Check immediately after use: At the end of each AI session, run tasklist to check for residual Chromium processes
  • Avoid long periods of unattended operation: Do not leave headless browsers running unattended for long periods. If you must use them, it is recommended to set up scheduled restarts or process timeouts

🧰 Troubleshooting Guide

If you encounter the following phenomena while using Playwright, it may indicate that the above incident is recurring.

Symptom Quick Reference Table

Symptom Troubleshooting direction Urgency
Computer fan spinning wildly, system slowing down Open Task Manager and check whether there are multiple chrome.exe processes (each using 200-500MB of memory) 🔴 Handle immediately
AI agent gets slower with every reply Check whether every AI message loop triggers a browser screenshot/snapshot 🟠 Optimize as soon as possible
pnpm test:e2e The fan is still spinning after it finishes running Check whether there are residual Chromium processes that were not closed by the test framework 🟠 Fix as soon as possible
Browser automatically pops up windows (headed) Confirm whether pw_core configuration was mixed in but headed mode was mistakenly started 🟡 Observe and adjust

Emergency stop-loss steps

If you find that CPU usage has already spiked abnormally:

# 步骤 1:立即检查 Chromium 进程数
tasklist /FI "IMAGENAME eq chrome.exe" 2>NUL

# 步骤 2:如果存在大量 Chromium 进程,强制关闭
taskkill /F /IM chrome.exe 2>NUL

# 步骤 3:关闭重开 AI 会话,确认浏览器工具已不在会话中
# 步骤 4:检查 .mcp.json,临时移除 pw_core/pw_visual 条目
# 步骤 5:复盘分析 — 是哪个 AI agent 行为触发了高频调用

Long-term regression checklist

After each use of Playwright, review the following items:

  • tasklist has no residual chrome.exe
  • Task Manager CPU usage has returned to normal levels
  • There are no abnormally dense browser call records in the AI session logs
  • Each app's vite dev server has been shut down normally
  • If it is a CI environment, check the Chromium process exit status code in the CI logs

AI Memory Update Template

Insert in all three places: CLAUDE.md / AGENTS.md / GEMINI.md (<300 words):

## Playwright 工具链

三件套职责:@playwright/test (CI 固化) | @playwright/cli (生成 skills) | playwright-mcp (AI 驱动浏览器)

命名:vitest→*.test.ts,playwright→*.spec.ts

⚠️ 浏览器进程安全规则:

- AI 驱动浏览器默认用 pw_visual(headed),仅 token 敏感场景用 pw_core
- 每次使用浏览器后检查任务管理器,确保 Chromium 进程已退出
- 禁止在 headless 模式下对 3D 大屏页面做高频截图
- 大屏 3D 页面优先用 pw_visual 驱动,避免无头模式 GPU 空转

规则:视觉对齐后必须用 @playwright/test 固化。

Environment notes

  • Node 22 + Windows: Add NODE_OPTIONS= prefix to all node/pnpm commands (clear the problematic NODE_OPTIONS=--use-system-ca)
  • git commit: Must use the git-commit skill (check remote commit-types.ts emoji + commitlint pre-validation + -F file method)
  • pre-commit hook: After modifying lint-staged.config.js, verify once that a commit can pass

Acceptance checklist

  1. pnpm install No errors
  2. pnpm exec playwright --version Outputs version number
  3. pnpm test:e2e All 3 tests pass (smoke + visual)
  4. pnpm run ci Full process passes (vitest → build → test:e2e)
  5. .mcp.json Includes pw_core/pw_visual
  6. .agents/skills/playwright-cli/ Has skill files
  7. The Playwright toolchain sections in the three AI memory locations are consistent
  8. Sub-app vite.config.ts ports are explicitly fixed
  9. artifacts/ is gitignored
  10. ⚠️ Headless browser security specification has been read: confirm the project belongs to the 3D large-screen category, prioritize using pw_visual (headed) rather than pw_core
  11. ⚠️ Browser process reclamation has been checked:tasklist /FI "IMAGENAME eq chrome.exe" No residual Chromium processes