mirror of
https://github.com/prdlk/dotfiles.git
synced 2026-11-06 12:37:37 +00:00
shell: fish functions -> ~/.local/bin executables + bash/zsh ports; manage ~/.agents
- 16 cross-shell utilities converted to sh/bash chezmoi executables: ai c2p cp-appid extract_agents fab gdc gh-sonr-org-migrate ghg-clone ghn gho git-summary launch_omp_livediff_overlay lc-elir mdcp mdp pj (ghg-clone not named ghg: unrelated cargo binary owns that name) - cwd/history helpers stay per-shell: yy c cd clip-last + ghg/ghn/gho cd-wrappers in bash/functions/ and zsh/functions/, loaded by rc files - fish keeps only shell-state functions; converted ones now hit PATH - cp-appid ignore gating moved to .local/bin path - dot_agents/skills: 82 skills materialized from dotstate storage so dot_claude skill symlinks resolve on fresh bootstrap; dotstate profile/symlinks.json released .agents/skills .bashrc .zshrc
This commit is contained in:
1 parent
6776366ce6
commit
6406208b35
637 files changed
+100297
-497
No files matched your search
@@ -0,0 +1,88 @@
|
||||
# Browser Rendering Gotchas
|
||||
|
||||
## Tier Limits
|
||||
|
||||
| Limit | Free | Paid |
|
||||
|-------|------|------|
|
||||
| Daily browser time | 10 min | Unlimited* |
|
||||
| Concurrent sessions | 3 | 30 |
|
||||
| Requests/minute | 6 | 180 |
|
||||
| Session keep-alive | 10 min max | 10 min max |
|
||||
|
||||
*Subject to fair-use policy.
|
||||
|
||||
**Check quota:**
|
||||
```typescript
|
||||
const limits = await puppeteer.limits(env.MYBROWSER);
|
||||
// { remaining: 540000, total: 600000, concurrent: 2 }
|
||||
```
|
||||
|
||||
## Always Close Browsers
|
||||
|
||||
```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(); // ALWAYS in finally
|
||||
}
|
||||
```
|
||||
|
||||
**Workers vs REST:** REST auto-closes after timeout. Workers must call `close()` or session stays open until `keep_alive` expires.
|
||||
|
||||
## Optimize Concurrency
|
||||
|
||||
```typescript
|
||||
// ❌ 3 sessions (hits free tier limit)
|
||||
const browser1 = await puppeteer.launch(env.MYBROWSER);
|
||||
const browser2 = await puppeteer.launch(env.MYBROWSER);
|
||||
|
||||
// ✅ 1 session, multiple pages
|
||||
const browser = await puppeteer.launch(env.MYBROWSER);
|
||||
const page1 = await browser.newPage();
|
||||
const page2 = await browser.newPage();
|
||||
```
|
||||
|
||||
## Common Errors
|
||||
|
||||
| Error | Cause | Fix |
|
||||
|-------|-------|-----|
|
||||
| Session limit exceeded | Too many concurrent | Close unused browsers, use pages not browsers |
|
||||
| Page navigation timeout | Slow page or `networkidle` on busy page | Increase timeout, use `waitUntil: "load"` |
|
||||
| Session not found | Expired session | Catch error, launch new session |
|
||||
| Evaluation failed | DOM element missing | Use `?.` optional chaining |
|
||||
| Protocol error: Target closed | Page closed during operation | Await all ops before closing |
|
||||
|
||||
## page.evaluate() Gotchas
|
||||
|
||||
```typescript
|
||||
// ❌ Outer scope not available
|
||||
const selector = "h1";
|
||||
await page.evaluate(() => document.querySelector(selector));
|
||||
|
||||
// ✅ Pass as argument
|
||||
await page.evaluate((sel) => document.querySelector(sel)?.textContent, selector);
|
||||
```
|
||||
|
||||
## Performance
|
||||
|
||||
**waitUntil options (fastest to slowest):**
|
||||
1. `domcontentloaded` - DOM ready
|
||||
2. `load` - load event (default)
|
||||
3. `networkidle0` - no network for 500ms
|
||||
|
||||
**Block unnecessary resources:**
|
||||
```typescript
|
||||
await page.setRequestInterception(true);
|
||||
page.on("request", (req) => {
|
||||
if (["image", "stylesheet", "font"].includes(req.resourceType())) {
|
||||
req.abort();
|
||||
} else {
|
||||
req.continue();
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
**Session reuse:** Cold start ~1-2s, warm connect ~100-200ms. Store sessionId in KV for reuse.
|
||||
Reference in new issue
Block a user