Migrating the browser extension codebase to TypeScript and other bug fixes

Engineering |
Migrating the browser extension codebase to TypeScript and other bug fixes

Introduction

We announced about a month ago that we revived our Google Chrome extension project and made some major improvements—user interface makeover, React migration, Firefox support, and going open source. It’s a great start, but we don’t stop there.

New changes

Since the announcement, we’ve implemented bug fixes and further codebase improvements. The asset metadata (i.e., asset ID, whether to save cookies and/or to bypass asset verification) that’s being persisted client-side isn’t being wiped out anymore when the user signs out. New assets are now being persisted in local storage properly. We also fixed the issue where the browser extension shows that it’s an existing asset even though that asset was removed via the Screenly web interface or via the REST API. To summarize, we applied fixes related to synchronizing browser storage with Screenly.

Regarding open source, we’ve now added a prerequisites section in the documentation so that users and potential contributors can get started with less hassle. We also added documentation on how developers can start making contributions to the project. Some parts of the new contribution docs were already in the main README, but having separate documentation for that makes it clearer.

We also migrated the codebase to TypeScript, which we’ll elaborate on in the next section.

Why migrate to TypeScript?

Our decision to migrate to TypeScript wasn’t easy or straightforward. We researched other developers’ stories about migrating to TypeScript, reverting to JavaScript, and other approaches. There’s no silver bullet for every problem. Every approach has its own benefits and trade-offs.

When we first migrated to TypeScript, we used any everywhere. While this is a neat feature that TypeScript offers (to allow a smooth transition from JavaScript), it’s not a good practice as it defeats the purpose of moving to a strongly-typed programming language.

Introducing type systems in the project has its pros and cons. With typing, it becomes easier to debug code. It also acts as documentation, alongside code comments. To justify this statement, we’ll demonstrate code snippets from our project. Here’s what our function createWebAsset looks like before TypeScript:

export function createWebAsset(user, url, title, headers, disableVerification) {
  // callApi is a wrapper function that we wrote for window.fetch
  return callApi(
    'POST',
    'https://api.screenlyapp.com/api/v4/assets/',
    {
      'source_url': url,
      'title': title,
      'headers': headers,
      'disable_verification': disableVerification,
    },
    user.token
  );
}

For contributors new to the project, it would be quite hard to identify what arguments to pass. Take the user parameter for instance. At first glance, it looks like data needs to be a JavaScript object, but it’s not particular about what attributes to include. We can get away with debugging it by temporarily putting console.log statements all over the place but it can be tiresome especially when things get quite complicated.

This is where TypeScript can be useful. Here’s what the createWebAsset function looks like right now:

export function createWebAsset(
  user: User,
  url: string,
  title: string,
  headers: object | null,
  disableVerification: boolean,
) {
  // callApi is a wrapper function that we wrote for window.fetch
  return callApi(
    'POST',
    'https://api.screenlyapp.com/api/v4/assets/',
    {
      source_url: url,
      title: title,
      headers: headers,
      disable_verification: disableVerification,
    },
    user.token,
  );
}


As seen on the snippet, user should be of User type. Here’s how the User type is defined:

export interface User {
  token: string;
}

This means that we should pass to createWebAsset a TypeScript object with a property named token, which should be a string. Developers won’t have to guess what kind of arguments to pass or rely on console.log statements.

With these improvements, TypeScript can detect errors that JavaScript might miss.

When not to use TypeScript?

Initially, our browser extension project was written in JavaScript. As the codebase grew larger, it became less readable and more prone to bugs that could have been caught earlier.

As mentioned earlier, TypeScript is not a “one size fits all” solution. It requires a learning curve, especially for developers who are used to JavaScript’s flexibility. There can be cases where TypeScript’s strictness might hinder rapid prototyping or experimentation. The tooling and ecosystem around TypeScript are still evolving, and there might be compatibility issues with certain libraries or frameworks.

What’s next?

The project remains open source, so we encourage everyone to contribute. If you find a bug, feel free to create an issue. Additionally, if you discover something that can be added or enhanced—whether it’s an internal change, a minor user interface fix, or a documentation update—feel free to open a pull request.

Picture of Nico Miguelino
Nico Miguelino View Profile
Nico maintains open source projects at Screenly.

Recent Posts

Display your best content with Screenly digital signs.

Screenly is loaded with features to make digital signage management easy.

footer screen image
manage cookies