Chuniversiteit logomarkChuniversiteit.nl
“Heap, Heap, Array!”

Frameworks for developing browser extensions

You probably wouldn’t build a modern web application without a framework, so why use vanilla JavaScript for your browser extension?

Two people awkwardly trying to moving a Chrome extension
I feel a bit puzzled about all these frameworks

My first two browser extensions in the Chrome Web Store, Jirleader and Alright, were written using plain JavaScript, without any external packages or bundlers. These extensions are small and don’t require much maintenance, so that’s totally fine.

I am currently working on a third browser extension that will take two years to develop and will also require regular maintenance, so this time I wanted a development environment that is a bit less spartan. More specifically, I wanted a setup that enables me to easily:

  • run everything in Docker containers so I don’t have to deal with

  • download and manage dependencies using a package manager

  • write my app using TypeScript and React, and have everything transpiled automatically to JavaScript

  • see changes in real-ish time without having to mash my browser’s refresh button all the time

  • develop browser extensions that work consistently across all major browser engines

  • test my own work using modern testing frameworks such as Jest and Playwright

First impressions

Link

If you have read last week’s paper summary, you’d know that Extensionizr is woefully outdated. I searched Google for frameworks that help with the development of browser extensions and found three that seem popular enough: Plasmo, WXT, and CRXJS. I tried them all, and sadly have to report that I was disappointed in all three.

Plasmo

Link

With almost 12k stars on GitHub, Plasmo appears to be the most popular framework for developing browser extensions with React.

Plasmo’s README refers to itself as a Next.js for browser extensions, and I can definitely see why. It’s a batteries-included framework that supports all major web browsers (Chrome, Edge, Safari, and Firefox), comes with first-class support for React and TypeScript, , live reloading, and more.

Plasmo is developed by Plasmo Corp., which like Vercel, tries to make money from the framework by offering cloud services that make it a bit easier to publish your extensions to extension stores. Some developers might not like this. I personally think it’s fine – it suggests that there’s at least one maintainer with a strong incentive to continue working on the framework.

“It’s fine” is also the best way to describe my first impressions of the framework. The documentation is alright, the examples all seem to work, as does the framework itself. I did run into a few issues – mostly related to node-gyp and live reload – but nothing major.

WXT

Link

Although WXT has fewer stars (7.2k) than Plasmo, it appears to be just as – if not more – capable and well-maintained as Plasmo. WXT supports the same things Plasmo does

Unfortunately, I could not get even the most basic example project working in Docker, so I quickly moved on to the next framework.

CRXJS

Link

CRXJS (3.3k stars) is even less popular than Plasmo and WXT. This is not entirely surprising, given that it has a smaller scope. CRXJS describes itself as a tool – or more accurately, a Vite plugin – for developing Chrome extensions.

CRXJS was the easiest of the three to set up, and live reloading also worked well most of the time. I therefore went ahead and built my first throwaway prototype using CRXJS, but I also noticed quite a few red flags:

  • The main branch had already been obsolete for years. To use CRXJS for new MV3 extensions, I had to install a beta version of the plugin that targets Vite 3 (which is also several years old by now). At the time of writing, the new version finally appears to be out of beta – but the website now shows a banner suggesting that the project has been abandoned. Yikes…

  • Despite CRXJS doing less than Plasmo and WXT, it somehow generates a lot more clutter in the root directory.

What I ended up using (for now)

Link

I built my second throwaway prototype using Plasmo. This time around I had far fewer issues with the initial setup, but as I kept tacking on new features to my prototype, the first cracks already started to reappear.

Live reloading works, but it’s surprisingly slow compared to HMR for normal web applications. And when it doesn’t work (e.g. due to an error) live reloading either fails silently or with a window.alert that says {} but nothing that actually tells you what is wrong. The console logs are also structured in a way that is not necessarily helpful (e.g. showing the most important information only at the top, which will nearly always be outside the current scroll area).

These issues are not the end of the world, but I may give WXT another try later this year again to see if things have improved. If so, I’ll let you know via an update to this post!