DEV Community

Rachel Harrison for Fellow Engineering

Posted on • Originally published at fellow.engineering on

Managing Browser Extension Versions with Gulp

How did we get here?

While developing the second version of the Fellow browser extension, we realized that our current solution for managing the extension for our different environments — finding and replacing all relevant variables in the code before uploading packages — was getting to be too much overhead. In the first version of the extension, the only place where we needed a different value for each environment was for the source URL of an iframe, which was easy to switch out manually when needed for local development, our staging environment, and production, as we could do it right before uploading the extension to Chrome or Firefox.

As we added more features to our extension, the list of places we needed to swap out URLs grew from one to three. Still, we managed this manually as we only had to do it a few times. There were a few developers working on the project, and we all changed the URLs back to match our staging environment when committing code. Then before uploading our extension for approval, we swapped them out for production. We knew this solution was far from ideal, but with only three places to swap out values and only a handful of developers who needed to remember where to swap them, it worked fine.

Then things got more complicated.

By the time the bulk of the development was done on the second large iteration of the extension, there were a dozen places that we’d need to swap out values. Additionally, it was no longer just the environment URL that we had to change — we also had a value to get the correct cookies, and another that acted as a flag for functionality that we needed only in our local environments. On top of that, with our extension now being a more robust project that was really taking off, it wasn’t hard to imagine that soon even more developers would need to run the extension locally to contribute to its development. The overhead of documenting all the spots to swap values, and which values to swap them with, would have been hard to maintain and lengthy to execute.

One half-measure would have been to pull all the values that needed to be swapped out of their files, and instead export them from a global config file. This solves the issue of having to document (or remember) all the places where values need to be swapped, but is still more overhead than we’d like. We’d still need to document somewhere what those values are for each environment, and generating the extension for a new environment would still involve editing a file.

Then we found a solution that allowed us target a specific environment for the extension with one command. Using Gulp we can run a command like gulp — config STAGING and we’ve generated a directory with a version of our extension targeting the staging environment, ready to upload.

How does it work?

In the end, it’s really just a fancy version of the config file solution. All the values for an environment are placed together in a config file, one file for each environment. These are named with the name of the environment like config.STAGING.json. Then, when the gulp command is run and the environment is specified, a version of the extension with the correct values for that environment is generated and dumped into a specified folder.

The bulk of this process in defined in a file called gulpfile.js at the top level of our extension directory. When gulp is run this file takes the appropriate config file and dumps those values into a file called config.js. This file is where the values are imported from elsewhere in the code. This config file and all the other extension files are copied to a separate folder, ready to be uploaded.

So how does it do that? It defines four primary functions and executes them in order:

  1. First it deletes any contents of the target directory, to make space for the newly compiled one.
  2. Then it makes copies of all extension files, excluding config files, and adds them to the target directory.
  3. Next, it selects the correct config file, based on the config flag passed when the command is run.
  4. Finally, it writes the contents of the selected json file to config.js in the target directory. Once these four steps are complete, all the extension source code and a config file with values for the target environment are in a single directory, ready to be uploaded!

What else can we do?

We’ve already extended this basic concept in a few ways. In addition to creating config..json files for development, staging, and production, we can also create what I’ve been calling “on the fly configs”. These are config files to target rarely used environments, like sandboxes, or environments without consistent URLs, like the environments generated by our CI process. Unlike the other environments’ config files, these ones are not tracked in Git. Instead, they are intended to be short-lived files that are created when necessary and then discarded.

Another complication that arose surrounds the config file for local development. Every developer at Fellow has a different URL for local development. If I were to commit a config file with my URL in it, that wouldn’t be helpful for the next developer looking to run the extension to point at their local environment. Instead, the config file for local environments is not tracked in Git, but a file called config.template is. This template contains json to be copied to a local environment config file and populated with the correct values for that developer’s local setup.

There are also other applications for this than just switching environments! For example, we could add a flag like --browser and define different config files for Chrome and Firefox. Currently in our extension, the browsers only differ in one way: the path to use to import images. We’re checking if we’re in Firefox before adding any image so that we can import it in the correct way. Instead, we could define the path to an image for Firefox in one config file and to an image for Chrome in another, then use Gulp to generate the correct version of the extension for upload.

These are just a few ways we’ve already expanded our use of Gulp, and there are many other possibilities! It’s helped us improve our development workflow and has reduced the amount of things we need to remember. I hope these tips will help you out too, and am excited to hear about any other interesting use cases for Gulp with browser extension management!

For a larger example (including extra features such as watching files for changes, and a sample extension), check out this great post!


Top comments (0)