How we use web browser extensions to build incremental web features at Viki

Weiyuan
Viki Blog
Published in
4 min readJan 22, 2019

--

Recently, we had a problem that we needed to solve. We needed to add a new feature to our Soompi website that gave our editorial staff “one-click access” to edit an article. However, that feature was only to be limited to a small set of users (our editorial staff), and will not be used by anyone else.

It’s relatively simple to achieve that in a monolithic service where staff related services are housed on the same application as the web client. But modern day applications don’t tend to work that way — we advocate developing decoupled yet highly cohesive services instead, or what is known as Service-Oriented Architecture (SOA).

With decoupled services comes with teams that are usually in charge of different services — which makes cross development difficult. Just to mention a few issues faced — such as different languages or frameworks utilized. Or time to familiarize with the code base before doing anything ambitious. Perhaps even small differences in team culture makes it even harder to quickly acclimate and facilitate agile development.

In light of this problem, why not write a browser extension instead of creating or augmenting services as the solution. One might even argue that this is an independent service, where the inputs are the URL and the rendered HTML within the page, while the outputs are the desired hidden content, redirects and toggles within the page, reserved for the intended audience where the extension is made available to.

So, where do we start?

  1. Decide the browser — Everyone may not have the same preferred browser, which makes adoption not 100% foolproof. After internal discussions and checking browser usage, Chrome seem like the clear choice. Its popularity ahead of other browsers makes it more easily marketable to my colleagues.
  2. Decide the feature — Features can be implemented from the context menu (AKA right click menu) - which services basic redirects and view manipulation. Another element of the Chrome Extension API is the browser action (the icon on the top right hand of the browser) and popup - a separate view rendered on top of your web page, giving you more liberty in designing elements to interact with other services. One thing to note here is that this is not server-side logic, and I would recommend against adding logic that is prone to creating security risks for yourself or your company.
  3. (EXTRA) Decide the framework (and to a lesser extent, libraries too)If you’re implementing a popup, why not write it on a JS framework like Angular or library like React. The benefit that comes with the above are the ease of integrating tools that are already publicly available (such as those that can be installed using NPM). Most importantly, these items have accompanying standards and modularized ways to structure the code, something that is a must-have for ensuring that future developers can understand and build on top of, with ease.
  4. Publication cost — Lastly, prepare $5 before you publish your application. You have to spend this dough here, but the silver lining is that this is a one time cost for publishing 20 applications under your account.

Implementation

For this extension, we will be creating a simple contextual menu that adds options depending on the page we’re on. We’ll also change the color of the browser action icon when its on our domain — additional UX design here to hint that the extension is available when visiting our website.

Before you start, you need to prepare a manifest file, for the various entry points of scripts and views, image assets, and information about your extension.

From the above, note the items that are crucial to the feature sets of this extension: context-menu, browser-action and popup.

For context-menu, it can be done very quickly by providing the name of the menu items and callbacks destined to be in the right-click menu in a single script. However, this could also make it hard to maintain — so why not modularize it? To start, we need a building block for a menu item.

From the above we established a base class that can used to modularize our context menu logic. Here’s how it was done for the root menu item that was implemented with MenuItem.

While we did not establish a callback here, you could implement it in any of your other menu item instances, and perhaps trigger a different URL in a different tab:

chrome.tabs.create({ url: URL })

And finally, context-menu.js to initialize the menu items (in a Depth-first search like manner)

Next off, we have browser-action which deals with the logic of how the icon is displayed in Chrome toolbar

The implementation is relatively simple — we establish a means to update the icon as the faded variant and the regular variant. The mechanism is triggered by two listened events — when the URL is updated for the currently active tab, and when the active tab in Chrome is changed.

The above was done in the context of Soompi, where we had identified with the problem statement earlier. Another innovation that was not discussed here was the addition of React modules in the rendered popup.html, triggered by clicking the browser action icon. This is similar to web services that uses React, with a rendered HTML view that includes the scripts which invokes the relevant components for various utilities.

In retrospect, this isn’t a novel idea. In fact, someone I knew already worked on a similar extension tool before, which gave more weight to making this a reality even as a side project. If anything, it drove us to create a modern Chrome extension with newer offerings backed with relevant technologies used in our production web services, instead of defaulting to vanilla JavaScript.

--

--

Senior Engineering Manager, Ascenda Loyalty | Former Engineering Manager, Grab | Former Director of Engineering, ZilLearn | bit.ly/weiyuan