feat(browser): migrate from webextension-toolbox to WXT framework#859
feat(browser): migrate from webextension-toolbox to WXT framework#859
Conversation
Replace deprecated webextension-toolbox with modern WXT framework for improved developer experience and active maintenance. This migration addresses the issue where webextension-toolbox hasn't been updated in 4 years. Key changes: - Replace webextension-toolbox with WXT framework - Restructure project to use entrypoints/ and public/ directories - Convert background/content scripts to WXT format with defineBackground/defineContentScript - Add wxt.config.ts for centralized configuration - Migrate all 11 languages i18n support to new structure - Update build scripts and dependencies - Remove deprecated manifest.json (now auto-generated) - Fix TypeScript configuration to extend WXT types Benefits: - Active framework with regular updates - Better development experience with HMR and Vite integration - Smaller bundle size and improved build performance - Modern toolchain with TypeScript-first approach - Unified cross-browser extension development
…ependencies Remove unused dependencies and configurations left over from webextension-toolbox migration to WXT. Changes: - Remove @types/webextension-polyfill dependency (WXT provides built-in types) - Remove browserslist configuration (not needed for WXT) - Update archive script path reference - Clean up package.json for WXT-only setup This reduces dependency footprint and eliminates potential conflicts with WXT's built-in tooling.
|
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. WalkthroughMigrates the browser extension to WXT: adds WXT config, entrypoints for background and content scripts, and TypeScript setup; updates package scripts and CI to run wxt prepare; ignores WXT outputs; replaces legacy manifest and background script with WXT-driven equivalents. Changes
Sequence Diagram(s)sequenceDiagram
participant Br as Browser
participant BG as Background (defineBackground)
participant Tabs as chrome.tabs
participant CS as Content Script (defineContentScript)
note over Br,BG: Extension startup
Br->>BG: Initialize background
BG->>Tabs: query({}) to list tabs
loop For each tab
BG->>BG: Validate tab (id, url, not discarded, github.com)
alt Valid GitHub tab
BG->>Br: Insert CSS (scripting.insertCSS)
BG->>Br: Execute JS (scripting.executeScript)
else Invalid/unsupported
BG-->>BG: Skip
end
end
note over Br,CS: On matched GitHub pages
Br->>CS: Load content script (matches, runAt, allFrames)
CS->>CS: main() → init DOM and integration
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Summary of ChangesHello @yamadashy, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request undertakes a significant modernization of the browser extension's build infrastructure by migrating from the outdated Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
Deploying repomix with
|
| Latest commit: |
96a6c17
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://6eabf303.repomix.pages.dev |
| Branch Preview URL: | https://feat-browser-wxt.repomix.pages.dev |
There was a problem hiding this comment.
Pull Request Overview
This PR migrates the browser extension from the deprecated webextension-toolbox to the modern WXT framework. The migration addresses the maintenance and security concerns of using an unmaintained build tool while preserving all existing functionality.
Key Changes
- Replace webextension-toolbox with WXT framework (v0.20.11) for modern build tooling
- Restructure project files to follow WXT conventions with
entrypoints/andpublic/directories - Convert background and content scripts to WXT format with proper TypeScript definitions
Reviewed Changes
Copilot reviewed 8 out of 42 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
browser/wxt.config.ts |
New WXT configuration file replacing manual manifest.json with programmatic manifest generation |
browser/tsconfig.json |
Updated to extend WXT's TypeScript configuration |
browser/package.json |
Updated build scripts and dependencies for WXT framework |
browser/entrypoints/content.ts |
Content script migrated to WXT format with defineContentScript wrapper |
browser/entrypoints/background.ts |
Background script migrated to WXT format with defineBackground wrapper |
browser/app/scripts/background.ts |
Removed old background script file |
browser/app/manifest.json |
Removed manual manifest (now auto-generated by WXT) |
browser/.gitignore |
Added WXT-specific build directories |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #859 +/- ##
=======================================
Coverage 88.85% 88.85%
=======================================
Files 109 109
Lines 7575 7575
Branches 1423 1423
=======================================
Hits 6731 6731
Misses 844 844 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Code Review
This pull request successfully migrates the browser extension from the deprecated webextension-toolbox to the modern WXT framework, which is an excellent improvement for the project's long-term maintainability and developer experience. The changes correctly restructure the project, update dependencies, and replace the static manifest with a wxt.config.ts file. My review provides suggestions to enhance the new implementation by improving the robustness and performance of the background script and increasing the maintainability of the WXT configuration file.
| chrome.tabs.query({}, async (tabs: chrome.tabs.Tab[]) => { | ||
| for (const tab of tabs) { | ||
| try { | ||
| await injectContentToTab(tab); | ||
| } catch (e) { | ||
| console.error(e); | ||
| } | ||
| } | ||
| }); |
There was a problem hiding this comment.
The current code iterates through tabs and injects scripts sequentially using await in a for...of loop. This can be slow if the user has many tabs open. To improve performance on extension startup, you can process tabs in parallel. Since injectContentToTab handles its own errors, you can call it for each tab without waiting for it to complete.
chrome.tabs.query({}, (tabs: chrome.tabs.Tab[]) => {
// Process tabs in parallel for faster startup.
tabs.forEach((tab) => injectContentToTab(tab));
});Fix TypeScript compilation errors in CI by removing dependency on WXT's auto-generated .wxt/tsconfig.json file which doesn't exist during lint phase. Changes: - Remove "extends": "./.wxt/tsconfig.json" from tsconfig.json - Add manual type definitions for WXT global functions (defineBackground, defineContentScript) - Include proper file paths and type declarations - Ensure CI can run lint checks before WXT generates its configuration This resolves the CI error: "Cannot read file '.wxt/tsconfig.json'" during the lint step.
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (3)
.github/workflows/ci.yml (1)
109-111: Cache the browser package lockfile for faster CI.setup-node’s npm cache currently keys off the root lockfile. Point it at browser/package-lock.json in the browser jobs.
Apply this diff in both “lint-browser” and “test-browser” jobs:
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # ratchet:actions/setup-node@v4 with: node-version-file: .tool-versions - cache: npm + cache: npm + cache-dependency-path: browser/package-lock.jsonAlso applies to: 206-208
browser/entrypoints/content.ts (1)
151-163: Avoid running in iframes unless needed.Running in all frames can cause redundant observers and work. If you don’t depend on iframes, set allFrames to false.
Apply this diff:
- allFrames: true, + allFrames: false,browser/package.json (1)
6-17: WXT scripts look solid; a couple of nits.
- Nice: prepare/dev/build/zip per-browser are aligned with WXT.
- Consider relaxing "engines.node" to ≥20 to match broader contributor environments and your root test matrix.
- Optional: document that
npm run prepareis required locally before lint/tests (you already do this in CI).Apply this diff if you want to relax engines:
"engines": { - "node": ">=24.0.1" + "node": ">=20.0.0" }Also applies to: 22-23, 43-45
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (9)
browser/package-lock.jsonis excluded by!**/package-lock.jsonbrowser/public/images/icon-128.pngis excluded by!**/*.pngbrowser/public/images/icon-16.pngis excluded by!**/*.pngbrowser/public/images/icon-19.pngis excluded by!**/*.pngbrowser/public/images/icon-32.pngis excluded by!**/*.pngbrowser/public/images/icon-38.pngis excluded by!**/*.pngbrowser/public/images/icon-48.pngis excluded by!**/*.pngbrowser/public/images/icon-64.pngis excluded by!**/*.pngbrowser/public/images/icon.svgis excluded by!**/*.svg
📒 Files selected for processing (10)
.github/workflows/ci.yml(2 hunks)browser/.gitignore(1 hunks)browser/app/manifest.json(0 hunks)browser/app/scripts/background.ts(0 hunks)browser/entrypoints/background.ts(1 hunks)browser/entrypoints/content.ts(2 hunks)browser/package.json(2 hunks)browser/tsconfig.json(1 hunks)browser/types.d.ts(1 hunks)browser/wxt.config.ts(1 hunks)
💤 Files with no reviewable changes (2)
- browser/app/scripts/background.ts
- browser/app/manifest.json
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Cloudflare Pages
🔇 Additional comments (4)
browser/.gitignore (1)
10-11: Good addition: ignore WXT build outputs.Ignoring .output/ and .wxt/ matches WXT’s generated artifacts. No concerns.
browser/entrypoints/content.ts (1)
1-2: Confirm CSS bundling path.Importing './styles.css' is fine; WXT will bundle it into the content script. Ensure the file lives under entrypoints or is reachable by Vite.
browser/wxt.config.ts (1)
8-36: Keep manifest version in sync, trim permissions, and simplify WAR.
- Source version from package.json to avoid drift.
- If background stops injecting, remove "scripting" to reduce attack surface.
- Use a wildcard for icons to avoid manual maintenance.
Apply this diff:
-import { defineConfig } from 'wxt'; +import { defineConfig } from 'wxt'; +import pkg from './package.json' assert { type: 'json' }; @@ - version: '1.0.1', + version: pkg.version, @@ - permissions: ['scripting'], + // permissions: [], // No programmatic injection needed; rely on content_scripts @@ - web_accessible_resources: [ - { - resources: [ - 'images/icon-16.png', - 'images/icon-19.png', - 'images/icon-32.png', - 'images/icon-38.png', - 'images/icon-48.png', - 'images/icon-64.png', - 'images/icon-128.png', - ], - matches: ['https://github.com/*'], - }, - ], + web_accessible_resources: [ + { resources: ['images/*.png'], matches: ['https://github.com/*'] }, + ],Note: JSON import requires Node ≥20 (you’re on ≥24).
browser/entrypoints/background.ts (1)
1-56: Remove manual content-script injection; WXT already injects.This duplicates the content script declared via defineContentScript and risks double execution, brittle manifest coupling, and slower startup. Let WXT handle injection.
Apply this diff to simplify:
-export default defineBackground(() => { - const injectContentToTab = async (tab: chrome.tabs.Tab): Promise<void> => { - if (!tab.url) return; - if (tab.discarded) return; - if (tab.id === undefined) return; - if (!tab.url.startsWith('https://github.com/')) return; - try { - const manifest = chrome.runtime.getManifest(); - if (manifest.content_scripts?.[0]?.css) { - await chrome.scripting.insertCSS({ target: { tabId: tab.id }, files: manifest.content_scripts[0].css }); - } - if (manifest.content_scripts?.[0]?.js) { - await chrome.scripting.executeScript({ target: { tabId: tab.id }, files: manifest.content_scripts[0].js }); - } - } catch (error) { - console.error('Error injecting content script:', error); - } - }; - chrome.tabs.query({}, async (tabs: chrome.tabs.Tab[]) => { - for (const tab of tabs) { - try { - await injectContentToTab(tab); - } catch (e) { - console.error(e); - } - } - }); -}); +export default defineBackground(() => { + // No-op: WXT injects content scripts declared via defineContentScript. +});Follow-up: If you adopt this, drop "scripting" from permissions in wxt.config.ts.
Summary
This PR migrates the browser extension from the deprecated
webextension-toolboxto the modern WXT framework. The migration addresses the issue where webextension-toolbox hasn't been updated in 4 years and provides significant improvements to the development experience.Why this change?
Key Changes
Framework Migration
entrypoints/andpublic/directories (WXT convention)defineBackground/defineContentScriptwxt.config.tsfor centralized configuration replacing manual manifest.jsonFunctionality Preservation
Build System Updates
wxt,wxt build,wxt zip)Verification
Files Changed
Added:
browser/entrypoints/background.ts- Background script in WXT formatbrowser/entrypoints/content.ts- Content script in WXT formatbrowser/entrypoints/styles.css- Content script stylesbrowser/wxt.config.ts- WXT configurationMoved:
browser/app/_locales/*→browser/public/_locales/*(11 languages)browser/app/images/*→browser/public/images/*(icon assets)Removed:
browser/app/manifest.json(now auto-generated by WXT)browser/app/scripts/background.ts(migrated to entrypoints)Updated:
browser/package.json- Scripts, dependencies, removed browserslistbrowser/tsconfig.json- Extend WXT typesbrowser/.gitignore- WXT-specific directoriesChecklist
npm run testnpm run lint