Featured image of post Developing Browser Extensions with Manifest V3 Featured image of post Developing Browser Extensions with Manifest V3

Developing Browser Extensions with Manifest V3

A beginner's guide to building modern browser extensions compliant with Chrome's Manifest V3 standard.

Manifest V3 is now the official and mandatory specification for building Google Chrome extensions. With the deprecation of Manifest V2, developers must adopt non-persistent Service Workers for background processing and adapt to the declarative net request model. This guide explains the core architectural shifts in Manifest V3 and provides a simple walkthrough of setting up a compliant extension.


1. Primary Shifts from Manifest V2 to V3

Manifest V3 (MV3) was designed to make browser extensions more secure, privacy-respecting, and performant.

1) Transitioning Background Pages to Service Workers

In MV2, extensions ran persistent background pages (background.js). In MV3, background scripts are replaced by Service Workers. Service Workers are ephemeral—the browser terminates them when idle to conserve system memory. Because variables in memory do not persist, developers must store application state using the chrome.storage API.

2) Network Interception with declarativeNetRequest

The old webRequest API allowed extensions to intercept and modify all incoming and outgoing network traffic using JavaScript. Due to security concerns, MV3 enforces the declarativeNetRequest API. Instead of executing custom logic on every request, extensions register declarative blocking rules that the browser processes natively.

3) Disallowing Remotely Hosted Code

For security auditing, extensions are no longer permitted to download and run external JavaScript files (e.g., loading jQuery or Google Analytics from a CDN). All code executed by the extension must be bundled locally inside the extension package.


2. Basic Manifest V3 File Structure

Here is a bootstrap implementation for an extension that opens a popup UI.

1) The Configuration File: manifest.json

Define the metadata, permissions, background service worker, and user interface actions:

{
  "manifest_version": 3,
  "name": "NetGuide MV3 Sample",
  "version": "1.0.0",
  "description": "A bootstrap extension demonstrating Manifest V3 features.",
  "permissions": [
    "storage",
    "activeTab"
  ],
  "background": {
    "service_worker": "background.js"
  },
  "action": {
    "default_popup": "popup.html",
    "default_icon": "icon.png"
  }
}

2) The Background Script: background.js

Implement event-driven handlers that respond when needed:

// Register default state on installation
chrome.runtime.onInstalled.addListener(() => {
  chrome.storage.local.set({ extensionActive: true });
  console.log("Extension installed and initialized.");
});

// React to tab activation changes
chrome.tabs.onActivated.addListener((activeInfo) => {
  chrome.storage.local.get(["extensionActive"], (result) => {
    if (result.extensionActive) {
      console.log(`Active tab shifted to: ${activeInfo.tabId}`);
    }
  });
});

3) The UI: popup.html and popup.js

Design the HTML interface and load the local popup script:

<!-- popup.html -->
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <style>
    body { width: 180px; font-family: sans-serif; padding: 10px; }
    button { width: 100%; padding: 6px; background: #2563eb; color: white; border: none; border-radius: 4px; }
  </style>
</head>
<body>
  <h4>NetGuide Tool</h4>
  <button id="action-btn">Check Status</button>
  <script src="popup.js"></script>
</body>
</html>
// popup.js
document.getElementById('action-btn').addEventListener('click', () => {
  chrome.storage.local.get(["extensionActive"], (result) => {
    alert(`Extension active status: ${result.extensionActive}`);
  });
});

3. Development Tips and Debugging

  • Handling Idle Timeouts: Because MV3 Service Workers stop running when idle, standard Javascript timers like setInterval will fail. Use the chrome.alarms API to schedule periodic processes.
  • Console Audits: To load your extension, open chrome://extensions in Google Chrome, enable “Developer Mode,” click “Load unpacked,” and select your development folder. Check background messages by clicking the “Inspect views: Service worker” link.

4. Conclusion: Navigating Manifest V3

While the transition to Manifest V3 initially introduced limits on specific APIs (affecting adblockers and security tools), the platform has stabilized. Implementing extensions under MV3 ensures that your plugins conform to modern browser security standards, providing users with a safe, optimized browsing experience.