Since 1999, browser extensions have given developers the ability to customize and enhance their web browsing experience. However, through the years, extension development has become more challenging as different browsers entered the market and introduced their own unique extension APIs. Luckily, in 2015 the W3C created a single standard API for browser extensions with the goal of creating a uniform landscape for browser extension development. Even though there now exists a standard, there are still many differences between Chrome, Firefox, Opera and Edge. In this article, we will cover the difficulties of building a cross-browser extension and provide a solution to overcome those challenges.

The four common challenges faced when building a cross-platform browser extension are:

  • Manifest management
  • API inconsistencies
  • Browser Action differences
  • JavaScript support

Manifest Management

The first challenge is the difference between manifest.json files used by browsers. Browsers rely on the manifest to describe the functionality of the extension and to provide the order of operations required to run the extension. Although there are many similarities between manifests used by different browsers, there are also breaking differences that cause interoperability issues. To avoid this, use a different manifest file per browser and choose which manifest to use during build time.

Start by creating a NodeJS function called build where a browser argument can be used to indicate which manifest to use during build time. Then when running node build --browser=chrome, the build function will use the Chrome version of the manifest.

Future Challenges with Browser Manifests

Chrome released manifest V3 Preview/Alpha edition on October 31st, 2019 and with a stable release scheduled for 2020. The new manifest version proposes the greatest change to the manifest schema to date as it alters how extensions will work with browsers. With that said, by following the recommended structure, we were able to create compatibility between the different manifest versions.

API Inconsistencies

Differences with API namespace and function coverage is usually the primary reason that developers resort to creating separate code bases per browser environment. However, by creating an abstraction between the browser and the extension, it is possible to manage the API differences.

Browser Service

In the illustration above, the BrowserService contains all the browser API functions used throughout the extension. This abstraction layer enables the developer to implement more complex logic on top of the provided abstraction without needing to handle all the complexities and differences between browsers. Although the above illustration provides a better development experience, it does come at a performance cost since the extension will need to decide which function to use in real-time. The good news is that this performance loss will be eliminated by modifying the build (node build --browser=chrome) to handle which browser variant of the BrowserService to use during compilation time.

Unavoidable Complexities

There will be scenarios where APIs that exist on one browser may not exist in other browsers. For some of these scenarios, there are polyfills and workarounds but these come at the cost of reliability or are lacking full API support.

Browser Action Differences

There are minimal differences regarding how browser actions are implemented within browsers. The key difference is the allowed maximum width and height of the browser action popover. There are two ways to overcome this. The easy way is to find the greatest common width and height between all browsers and set that as the width and height. The slightly more challenging way is to set the maximum width and height allowed for that browser dynamically during build time.

JavaScript Support

On top of the issues mentioned above, extensions also suffer the same JavaScript API incompatibilities faced by websites when building modern web applications. This is one of the easier challenges to conquer. Through the use of JavaScript compilers like Babel, it has become possible to downgrade the JavaScript used within the extension to one supported by the browser variant used. However, it is recommended to set targets used by Babel during the build time and not create a generic target. With this, modern browsers can still take advantage of the modern APIs and benefit from their performance gains.

Join DISQO.

If building powerful browser extensions on a modern tech stack sounds like a dream job to you, check us out at DISQO. We are hiring!