Skip to content

perf(content): minify prod bundle, throttle screenshot drag, reuse ghost-text overlay - #152

Open
zhongnansu wants to merge 1 commit into
mainfrom
fix/content-perf
Open

perf(content): minify prod bundle, throttle screenshot drag, reuse ghost-text overlay#152
zhongnansu wants to merge 1 commit into
mainfrom
fix/content-perf

Conversation

@zhongnansu

Copy link
Copy Markdown
Member

Three independent content-script / build performance fixes.

1. Minify production bundle

esbuild.config.js shipped content.js unminified to every page on every load. Now minify: !isWatch — production builds minify, npm run dev/watch stays readable for debugging.

2. rAF-coalesce screenshot drag

The screenshot drag registered an unthrottled document mousemove that mutated rect.style.{left,top,width,height} on every pixel move (60+ reflows/sec). Now the latest coords are stored and a single requestAnimationFrame applies them once per frame; cancelAnimationFrame fires on drag-end / mode-exit (no leak, no stale write). The final captured rect is computed directly from the mouseup event, so it stays exact.

3. Reuse ghost-text overlay

showGhostText() destroyed and rebuilt the entire Shadow DOM overlay (and called getComputedStyle) on every keystroke. Now the host is built once and reused; only the ghost text content updates per call, and getComputedStyle-derived styles recompute only when the target textarea changes. Added a guard so a detached / 0×0 textarea (SPA re-renders) hides the overlay instead of desyncing.

Testing

  • Full build passes; affected unit tests pass (tests/trigger.test.js, tests/autosuggest-ghost-text.test.js), including new tests for rAF coalescing, overlay reuse, and the detached-textarea guard.

🤖 Generated with Claude Code

…e ghost-text overlay

- esbuild: minify production builds (minify: !isWatch); dev/watch stays
  readable. The unminified content.js shipped to every page on every load.
- selection.js/screenshot.js: coalesce screenshot-drag mousemove via
  requestAnimationFrame (one DOM write per frame instead of 60+/s reflows);
  cancelAnimationFrame on drag-end and mode-exit; final rect stays exact.
- ghost-text.js: build the Shadow DOM overlay once and reuse it instead of
  recreating it (and recomputing getComputedStyle) on every keystroke;
  recompute styles only on textarea change; guard detached/0x0 textareas.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions github-actions Bot added the tests Changes to test files label May 28, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📦 PR Preview — Ask AI Extension

Version: 1.2.1
Zip size: 335.9 KB

⬇️ Download artifact


Permissions

No permission changes detected. ✅


Preview Checklist

Before merging, manually test with the artifact above:

  • Load unpacked extension in chrome://extensions (developer mode)
  • Select text on any webpage and verify the trigger button appears
  • Click the trigger button and confirm the popup renders correctly
  • Right-click selected text and verify context menu items are present
  • Open a CSP-restricted page (e.g. chrome://extensions) and verify fallback works
  • Check the DevTools console for errors

Updated by PR Preview Bot — workflow run

@github-actions

Copy link
Copy Markdown
Contributor

📊 Code Coverage Report

File Coverage Status
proxy/src/index.js 98.0% 🟢
proxy/src/openai.js 100.0% 🟢
proxy/src/rate-limit.js 100.0% 🟢
proxy/src/validate.js 95.3% 🟢
src/options.js 97.6% 🟢
src/popup.js 100.0% 🟢
src/background/index.js 83.2% 🟢
src/content/api.js 88.2% 🟢
src/content/detection.js 99.3% 🟢
src/content/history.js 86.1% 🟢
src/content/image-capture.js 91.6% 🟢
src/content/presets.js 100.0% 🟢
src/content/prompt.js 97.4% 🟢
src/content/autosuggest/context.js 100.0% 🟢
src/content/autosuggest/debounce.js 100.0% 🟢
src/content/autosuggest/ghost-text.js 100.0% 🟢
src/content/autosuggest/index.js 75.9% 🔴
src/content/autosuggest/styles.js 100.0% 🟢
src/content/bubble/core.js 75.5% 🔴
src/content/bubble/history.js 85.3% 🟢
src/content/bubble/markdown.js 96.0% 🟢
src/content/bubble/stream.js 97.0% 🟢
src/content/bubble/styles.js 100.0% 🟢
src/content/shared/constants.js 100.0% 🟢
src/content/shared/dom-utils.js 100.0% 🟢
src/content/shared/preset-usage.js 91.8% 🟢
src/content/shared/state.js 100.0% 🟢
src/content/trigger/button.js 92.6% 🟢
src/content/trigger/progress-ring.js 100.0% 🟢
src/content/trigger/screenshot.js 98.7% 🟢
src/content/trigger/selection.js 81.8% 🟢
src/content/trigger/styles.js 100.0% 🟢
src/shared/autosuggest-limits.js 100.0% 🟢
src/shared/brand.js 100.0% 🟢
Overall 93.4% 🟢 PASS

Threshold: 80%

✅ Coverage meets the minimum threshold.


Updated by Code Coverage workflow

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

tests Changes to test files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant