Introduction
If you’ve worked in software development, then you may be familiar with the situation during a busy feature or maintenance sprint where pull requests are being produced left right and centre across a range of your team’s git repositories.
It can be tricky to determine immediately which repositories have active pull requests in need of review when using only conventional tools, e.g. slack threads, email notifications, without a good deal of searching first.
To tackle this issue, I designed and developed a utility chrome extension which allows you to quickly check for any active pull requests on repositories you choose to track. As a result, standing to save you time in the process.
In this blog I will cover my core learnings while developing this extension. However I’ll first give a brief overview of what a chrome extension is and how it compares to your standard web application for context.
Chrome Extensions vs. Web Applications
Photo by Rubaitul Azad on Unsplash
What is a Chrome Extension?
A chrome extension is a small piece of software that runs in the browser, which adds new features or modifies existing functionality. They sometimes offer a user interface (popup) accessible from the toolbar and can be used to perform tasks such as blocking ads or providing translation assistance etc. and are available from the Chrome Web Store.
The Similarities:
Fundamentally, a chrome extension uses the same web technologies as any other web application.
You have:
- HTML, CSS and JavaScript files:
These describe your user interface and the logic for your application for execution within the browser environment, as they do for a web application.
- JavaScript Frameworks/Libraries and Build Tools:
While not essential, just as it is possible to write web apps without them you are able to use JavaScript frameworks/libraries such as React/Vue alongside build tools such as webpack, babel etc.
The Differences:
The main differences between web apps and chrome extensions lie in how each type of application utilizes the browser under the hood, and the need for an extension to have a manifest.json file.
- Difference 1: The manifest.json
At a minimum, a chrome extension needs a manifest.json file. This tells the browser everything it needs to know to load, configure and display the extension. Without this file, the extension would cease to exist.
For example, the manifest.json is needed to inform the browser that the extension needs permission to use storage APIs to store/retrieve data from within the browser’s local storage for instance.
- Difference 2: Background and Content Scripts
In order to manipulate the browser, your extension needs a service worker.
For example, a service worker can be responsible for detecting changes to an extension’s local storage or rearranging chrome tabs for example.
A service worker runs as a thread within your browser to execute APIs enabling these activities. However, a service worker cannot directly alter the DOM of webpages you have open.
This is where a content script comes in (or an offscreen document, which won’t be discussed in this blog).
A content script provides APIs which can alter the content/styling of webpages. To coordinate changes to the DOM based on events detected within the service worker as described, a communication chain must be established. This is done by setting up a message passing API between the service worker and content script.
The Power of Browser Extensions:
Compared to a typical web application, setting up a communication chain to manipulate the DOM after a change is detected in the browser requires more work to achieve.
However, the core benefit of this setup is that a chrome extension can access a far greater range of additional, more powerful APIs than a web application can.
For example, a chrome extension can use the Extensions API for handling system access, tab manipulation, searching browser history, network request control functionality among many other purposes.
Reduced API access in Web Applications
Web applications can gain access to a smaller set of browser APIs which pose a lesser risk, such as allowing access to a device’s geolocation.
The reasoning for this architectural difference is due to security risks that web applications cannot mitigate against. Namely, malicious client-side code could be hosted on a web server and stand to use APIs in a myriad of harmful ways against the user.
This is a far less likely occurrence for a chrome extension which would undergo a thorough review process before release on the Chrome Web Store.
The manner of gaining access to the DOM and the more powerful functions chrome extension APIs can perform form the dividing line here. Now we have covered the fundamentals let’s discuss my learnings!
Tip #1 - Invest in creating a Mock for your API Integration
One of my first development mistakes was in accidentally making too many unauthenticated API requests to GitHub in lieu of working with a mock/double.
As I had experienced some initial trouble in setting up a testing environment for the extension, I had consequently put off setting in place a double for the GitHub REST API I could use during local development.
As a result, I was occasionally getting IP locked from making too many unauthenticated requests to the API.
This being, due to the frequency at which I was manually making and then checking small source code changes hadn’t inadvertently introduced bugs during core user flows, which naturally involved making lots of API requests.
The delays encountered due to this were fairly brief as I thankfully recognized them as they came through and aimed to be more intentional with my API calls.
However investing the time in setting up a mock, i.e. dockerized JSON server image or the like, could have definitely saved some time in retrospect.
Tip #2 - Use Plasmo to speed up your development workflow
Something else I wished I invested the time in, was looking further into finding tooling for showing your updated chrome extension’s popup as soon as modifications were made. Namely, I was looking for what many web framework build tools offer, the ability to provision a development server for your chrome extension.
When I started out this project, I did some initial research into this area and wasn’t able to find anything fulfilling this role. My approach was to manually reload the unpacked extension within the developer console after each new build.
I evidently didn’t search hard enough initially, as it was only later I discovered tools such as Plasmo existed for this purpose.
In retrospect, using Plasmo to channel a dev server from my build tool, Vite, would have saved me a lot of time, allowing for a quicker development flow.
Tip #3 - Use the chrome.alarms API to ensure reliable timer/alarms functionality
Later in development I realised I was likely approaching a stage at which I’d be ready to prepare the extension for release on the Chrome Web Store.
However there was still one major issue with functionality that had persisted.
Contrary to my initial assumptions, when the extension popup was closed the mechanism to automatically fetch active pull requests on a user’s tracked repositories also stopped running. This went against the feature requirement I had in providing the user with up to date tracking functionality.
I had naively assumed at first that any code I wrote in the background script would continue to run persistently regardless of whether the chrome extension popup was loaded or not. For example, code running on a loop through the web setInterval API.
This being as this was my experience and understanding in the context of background processes for loaded but inactive chrome tabs.
I presumed the same would apply for a chrome extension which was at the very least loaded in the user’s browser.
This however is not the case as I found the logic I had created to automate fetching of updated pull request numbers would at most run for 30 seconds before the thread died and with it any future scheduled fetches.
This is due to a behavior requirement of extensions using Manifest V3 which enforces service worker threads to be short lived. The aim of this design decision is to minimize browser resource usage, only running continuously if triggering API-related events occurs often enough in the worker.
Thankfully, there is an easy solution to ensure processes occur reliably to a set schedule. This is provided by the chrome.alarms API which offers alarm functionality for creating and triggering resilient alarms.
These alarms awaken the service worker through configured alarm event listeners, which in my case ensured the extension continuously made GitHub REST API calls at set intervals, e.g. every 1 or 5 minutes.
While admittedly a setback, through this experience I learnt a valuable piece of domain knowledge in chrome extension development.
Additionally, it also illustrated the importance of vetting your technical assumptions before planning and implementing architecture. It certainly would have saved me a good deal of time on reflection!
Key Learnings/Takeaways
In summary, when undertaking a chrome extension development project ensure you follow these steps to make your life easier!
🎭 Mock your API
🛠️ Use Plasmo for faster iterations
⏰ Use chrome.alarms for reliable scheduling
I hope this helps you to avoid some of the development pitfalls I ran into when you tackle your own projects!
If you have any questions or thoughts on what I’ve run through here, feel free to drop me a message in the article comments below or directly to my Linkedin profile as I’m happy to help!
Alternatively, if you’d like to check out the repo for the extension the link is below alongside docs you may find interesting.
Hope you have a great rest of your day!
Stephen
🔗 Links:
Github Repo: https://github.com/cyprste2717218/github-prs-chrome-extension
Plasmo Docs: https://docs.plasmo.com/
Chrome Extension Docs: https://developer.chrome.com/docs/extensions

Top comments (0)