Chrome MV3 extension makes Chrome/Windows laggy when loaded — how should I profile content scripts, MutationObservers, and timers?

10 views
Skip to first unread message

Jacob Lane

unread,
4:43 PM (6 hours ago) 4:43 PM
to Chromium Extensions

I’m building a personal Chrome MV3 extension. Chrome and my PC run normally when the extension is disabled, but as soon as I load the unpacked extension, Chrome starts feeling laggy/heavy.

I’m not asking anyone to debug private production code. I’ve redacted the real domains and replaced them with fake hosts.

Setup:

  • Chrome MV3 extension
  • Windows
  • Unpacked extension loaded through chrome://extensions
  • Content scripts injected on several specific web apps
  • Some content scripts use all_frames: true
  • Some scripts use MutationObserver
  • Some scripts use polling intervals, for example 2s/3s/5s/10s
  • Service worker has recurring alarms, including a 1-minute alarm
  • Disabling the extension fixes the lag

What I’m trying to find:

  1. How to identify which content script/service worker path is causing CPU/memory usage.
  2. Whether all_frames: true plus DOM scanning/MutationObservers is a likely cause.
  3. Best way to profile an unpacked MV3 extension.
  4. What patterns to avoid in content scripts that run on large SPA pages.

Minimal redacted manifest shape:

{ "manifest_version": 3, "name": "Redacted Extension", "version": "1.0", "permissions": ["storage", "scripting", "tabs", "alarms", "webNavigation"], "host_permissions": [ "https://app1.example.com/*", "https://app2.example.com/*" ], "background": { "service_worker": "service_worker.js", "type": "module" }, "content_scripts": [ { "matches": ["https://app1.example.com/*"], "js": ["content-a.js"], "all_frames": true, "run_at": "document_end" }, { "matches": ["https://app2.example.com/*"], "js": ["content-b.js"], "all_frames": true, "run_at": "document_end" } ] }

Example pattern I’m worried about:

const observer = new MutationObserver(() => { clearTimeout(debounceTimer); debounceTimer = setTimeout(scanPage, 250); }); observer.observe(document.body, { childList: true, subtree: true }); setInterval(scanPage, 5000); function scanPage() { const nodes = document.querySelectorAll("div, span, button, input"); for (const node of nodes) { // reads text/attributes and updates extension state } }

What should I check first? Should I profile through Chrome Task Manager, DevTools Performance, chrome://extensions service worker inspection, or another tool?

Github link for the repo is: https://github.com/jacobsscoots/CTL-Redacted

Reply all
Reply to author
Forward
0 new messages