<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Muhammad Aleem Naveed</title>
    <description>The latest articles on DEV Community by Muhammad Aleem Naveed (@m_aleem_naveed).</description>
    <link>https://dev.to/m_aleem_naveed</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4020323%2Fe326f799-b193-443a-b05a-6c68d3700551.png</url>
      <title>DEV Community: Muhammad Aleem Naveed</title>
      <link>https://dev.to/m_aleem_naveed</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/m_aleem_naveed"/>
    <language>en</language>
    <item>
      <title>Optimizing Network Interception in Manifest V3: Inside the Architecture of an Asynchronous Blocklist Extension</title>
      <dc:creator>Muhammad Aleem Naveed</dc:creator>
      <pubDate>Wed, 08 Jul 2026 00:52:41 +0000</pubDate>
      <link>https://dev.to/m_aleem_naveed/optimizing-network-interception-in-manifest-v3-inside-the-architecture-of-an-asynchronous-5c8p</link>
      <guid>https://dev.to/m_aleem_naveed/optimizing-network-interception-in-manifest-v3-inside-the-architecture-of-an-asynchronous-5c8p</guid>
      <description>&lt;p&gt;As Google Chrome completes the transition from &lt;strong&gt;Manifest V2&lt;/strong&gt; to &lt;strong&gt;Manifest V3&lt;/strong&gt;, Chrome extension development has fundamentally changed. Persistent background pages have been replaced with event-driven service workers, and the synchronous &lt;code&gt;webRequest&lt;/code&gt; API has largely given way to the declarative &lt;code&gt;declarativeNetRequest&lt;/code&gt; API.&lt;/p&gt;

&lt;p&gt;These changes require more than simple API replacements—they demand a different architectural approach.&lt;/p&gt;

&lt;p&gt;While building &lt;strong&gt;SaveYourself&lt;/strong&gt;, a productivity-focused Chrome extension that blocks distracting websites, intercepts network requests, and enforces focus sessions, I had to redesign the extension around Manifest V3's constraints while maintaining responsiveness and keeping resource usage low.&lt;/p&gt;

&lt;p&gt;This article explains some of the engineering decisions behind that architecture.&lt;/p&gt;




&lt;h1&gt;
  
  
  1. Designing for Ephemeral Background Service Workers
&lt;/h1&gt;

&lt;p&gt;Under Manifest V2, background scripts remained active for the lifetime of the browser session. This allowed developers to keep state in memory, but it also meant extensions continuously consumed system resources.&lt;/p&gt;

&lt;p&gt;Manifest V3 replaces this model with &lt;strong&gt;event-driven service workers&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A service worker starts only when an event occurs and is automatically terminated when it becomes idle. Any variables stored in memory disappear once the worker shuts down.&lt;/p&gt;

&lt;p&gt;Because of this, SaveYourself treats the background process as a &lt;strong&gt;stateless execution environment&lt;/strong&gt;. Persistent information—such as whether a focus session is active—is stored using &lt;code&gt;chrome.storage.local&lt;/code&gt; and retrieved whenever the service worker wakes up.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// background.js&lt;/span&gt;

&lt;span class="nx"&gt;chrome&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;runtime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onInstalled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;chrome&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;extensionActive&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;lockedDomains&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;chrome&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;runtime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onMessage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addListener&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sendResponse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;START_LOCK&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;handleSessionLock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sendResponse&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach ensures the extension behaves consistently across service worker restarts without relying on long-lived in-memory state.&lt;/p&gt;




&lt;h1&gt;
  
  
  2. Network Filtering with declarativeNetRequest
&lt;/h1&gt;

&lt;p&gt;One of the most significant Manifest V3 changes is the removal of the blocking version of &lt;code&gt;chrome.webRequest&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Instead of allowing JavaScript to inspect every outgoing request, Chrome now encourages extensions to define filtering behavior declaratively using the &lt;code&gt;declarativeNetRequest&lt;/code&gt; API.&lt;/p&gt;

&lt;p&gt;Rather than evaluating each request in JavaScript, SaveYourself converts the user's blocked websites into dynamic rules that Chromium applies internally. This allows network requests to be filtered directly by the browser engine, reducing extension overhead and improving privacy.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;updateSystemBlocklist&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;domainList&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newRules&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;domainList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;block&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;urlFilter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`*://*.&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/*`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;resourceTypes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;main_frame&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sub_frame&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;xmlhttprequest&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}));&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;oldRules&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;chrome&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;declarativeNetRequest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getDynamicRules&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;chrome&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;declarativeNetRequest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;updateDynamicRules&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;removeRuleIds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;oldRules&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rule&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;rule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;addRules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;newRules&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By delegating request filtering to Chromium itself, the extension avoids unnecessary JavaScript execution while still supporting dynamic, user-defined blocking rules.&lt;/p&gt;




&lt;h1&gt;
  
  
  3. Enforcing Focus Sessions Without Continuous Polling
&lt;/h1&gt;

&lt;p&gt;One of SaveYourself's primary goals is preventing users from modifying settings during an active focus session.&lt;/p&gt;

&lt;p&gt;Rather than keeping a persistent monitoring loop running, the extension uses browser-provided APIs to maintain lock state efficiently.&lt;/p&gt;

&lt;p&gt;When a focus session begins:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The session's expiration time is stored in &lt;code&gt;chrome.storage.local&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The popup interface checks that value whenever it opens.&lt;/li&gt;
&lt;li&gt;Background logic validates whether configuration changes are allowed.&lt;/li&gt;
&lt;li&gt;Scheduled browser alarms trigger events when the session ends.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This event-driven design eliminates the need for continuous polling while ensuring lock enforcement remains reliable across browser restarts and service worker lifecycles.&lt;/p&gt;




&lt;h1&gt;
  
  
  Lessons Learned from Building for Manifest V3
&lt;/h1&gt;

&lt;p&gt;Manifest V3 encourages developers to build extensions that are event-driven, resource-efficient, and privacy-conscious.&lt;/p&gt;

&lt;p&gt;Some of the most important architectural lessons from building SaveYourself include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Treat service workers as stateless execution environments.&lt;/li&gt;
&lt;li&gt;Persist important state using Chrome's storage APIs.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;declarativeNetRequest&lt;/code&gt; whenever browser-level filtering is appropriate.&lt;/li&gt;
&lt;li&gt;Prefer browser events and alarms over continuous polling.&lt;/li&gt;
&lt;li&gt;Design around asynchronous execution instead of persistent runtime state.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Although Manifest V3 introduces new constraints, those constraints also encourage cleaner architectures that rely more heavily on browser-native capabilities.&lt;/p&gt;

&lt;p&gt;For SaveYourself, embracing these patterns resulted in an extension that remains responsive while minimizing resource usage and staying within Chrome's modern security model.&lt;/p&gt;

&lt;p&gt;If you're interested in the implementation details, you can explore the source code on GitHub or install the extension directly from the Chrome Web Store.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>chromeextension</category>
      <category>programming</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
