[ PROMPT_NODE_24010 ]
Browser Rendering 常见陷阱
[ SKILL_DOCUMENTATION ]
# 浏览器渲染常见陷阱
## 层级限制
| 限制 | 免费 | 付费 |
|-------|------|------|
| 每日浏览器时间 | 10 分钟 | 无限制* |
| 并发会话 | 3 | 30 |
| 每分钟请求数 | 6 | 180 |
| 会话保持存活 | 最长 10 分钟 | 最长 10 分钟 |
*受公平使用政策约束。
**检查配额:**
typescript
const limits = await puppeteer.limits(env.MYBROWSER);
// { remaining: 540000, total: 600000, concurrent: 2 }
## 始终关闭浏览器
typescript
const browser = await puppeteer.launch(env.MYBROWSER);
try {
const page = await browser.newPage();
await page.goto("https://example.com");
return new Response(await page.content());
} finally {
await browser.close(); // 始终在 finally 中执行
}
**Workers 与 REST:** REST 在超时后自动关闭。Workers 必须调用 `close()`,否则会话将保持打开直到 `keep_alive` 过期。
## 优化并发
typescript
// ❌ 3 个会话(达到免费层级限制)
const browser1 = await puppeteer.launch(env.MYBROWSER);
const browser2 = await puppeteer.launch(env.MYBROWSER);
// ✅ 1 个会话,多个页面
const browser = await puppeteer.launch(env.MYBROWSER);
const page1 = await browser.newPage();
const page2 = await browser.newPage();
## 常见错误
| 错误 | 原因 | 修复 |
|-------|-------|-----|
| 会话限制超出 | 并发过多 | 关闭未使用的浏览器,使用页面而非浏览器 |
| 页面导航超时 | 页面加载慢或繁忙 | 增加超时时间,使用 `waitUntil: "load"` |
| 会话未找到 | 会话过期 | 捕获错误,启动新会话 |
| 评估失败 | DOM 元素缺失 | 使用 `?.` 可选链 |
| 协议错误:目标已关闭 | 操作期间页面关闭 | 在关闭前等待所有操作完成 |
## page.evaluate() 陷阱
typescript
// ❌ 外部作用域不可用
const selector = "h1";
await page.evaluate(() => document.querySelector(selector));
// ✅ 作为参数传递
await page.evaluate((sel) => document.querySelector(sel)?.textContent, selector);
## 性能
**waitUntil 选项(从快到慢):**
1. `domcontentloaded` - DOM 就绪
2. `load` - 加载事件(默认)
3. `networkidle0` - 500ms 内无网络活动
**阻止不必要的资源:**
typescript
await page.setRequestInterception(true);
page.on("request", (req) => {
if (["image", "stylesheet", "font"].includes(req.resourceType())) {
req.abort();
} else {
req.continue();
}
});
**会话重用:** 冷启动约 1-2 秒,热连接约 100-200 毫秒。将 sessionId 存储在 KV 中