Building a Vue.js composable for handling Feature Flags
Tags: vue, javascript, typescript, tutorial
Published: 2023-11-27 08:12:00

I recently had to implement a solution in our project that would enable us to have feature flags. The reason for having these flags was that mainly for streamlining the development process as they allow us to develop features and release them to production but they are hidden until the flag is set to true.

This allows testing more complex features in a proper production environment without actually causing issues to existing users.

If you would like to read more about the concept of feature flags implemented with Firebase Remote Config, I have published an article about this topic https://dev.to/jacobandrewsky/using-firebase-remote-config-for-feature-flags-2ji9

In this blog post however, I will guide you through the process of creating your own composable that will help you manage the feature flags in an easy way.

Enjoy!

## Feature Flag solutions

There are actually multiple ways you can do this so I wanted to show you some approaches that I have considered along the way and the final solution that me and my team decided to go with.

### Local object

The simplest solution out of all available approaches here is just this:

```ts
const flags = {
  'awesome_feature': false
}
```

This solution certainly works but it is not the best in terms of maintainability and execution (especially if you are not a technical person). It requires a developer to change the value of the flag in the code and publish the changes. Considering the complexity of certain development processess, hiding a feature could take hours while we sometimes need minutes.

### Content Management System

Yes, you read it correctly. CMS can also be used for handling feature flags. It is not its primary meaning but several web applications are already using content management systems and in the end, feature flags are just a key/value pairs that can be easily stored in a JSON file that we fetch from CMS.

### Feature Flag Software

There is actually several software providers that are focusing primarly on feature flag implementations like LaunchDarkly for example. They come with many interesting features that your business may need so I definitely recommend you to check it out if you have a big project and complex release process - LaunchDarkly could help you with it.

But in our case, we decided to go with Firebase Remote Config thanks to its simplicity and easiness of usage.

## Vue Composable

The implementation of the Vue composable that is responsible for handling feature flags will not differ that much depending on the path that you will choose in the previous point. The only crucial point is to choose if you should be fetching these flags directly from the frontend or maybe from your own server or middleware, for example:

```
Frontend -> CMS/FeatureFlagSoftware

or

Frontend -> Backend -> CMS/FeatureFlagSoftware
```

I personally prefer to have my own backend or middleware because then I can have full control over the flag invalidation process. I explained this issue here https://dev.to/jacobandrewsky/using-firebase-remote-config-for-feature-flags-2ji9

But coming back to the composable itself. What do we need in that composable?

First of all, it would be beneficial to have a type where we could store all our available feature flag names and then a type for key/boolean flag record:

```ts
type FeatureFlagName =
  | 'awesome_feature'
  | 'another_awesome_feature';

export type FeatureFlags = Record<FeatureFlagName, boolean>;
```

Then, we would need a Ref variable where we will be storing the flags and that will be easily available for usage across our application. As feature flags are global, I like to put this variable outside of scope of the composable itself so that components can share this state:

```ts
const flags = ref<FeatureFlags>({} as FeatureFlags);
```

And finally, the composable itself. There are two approaches here in terms of fetching the actual flags that are based purely on the Developer Experience. In my example `useApiClient` is a composable that is a wrapper around VueUse useAxios but you can use any other data fetching approach.

1. Fetching flags when `useFeatureFlags` composable is called

```ts
export const useFeatureFlags = () => {
  const { execute, data } = useApiClient<FeatureFlags>();

  onMounted(async () => {
    await execute('/flags');
    flags.value = data.value ? data.value : ({} as FeatureFlags);
  });

  return flags;
};
```

And then in the component use it like following:

```vue
<script setup lang="ts">
const featureFlags = useFeatureFlags();
</script>

<template>
  <AwesomeFeature v-if="featureFlags.awesome_feature" />
</template>
```

2. Fetching flags when `fetch` method from `useFeatureFlags` composable when needed

```ts
export const useFeatureFlags = () => {
  const { execute, data } = useApiClient<FeatureFlags>();

  const fetch = () => {
    await execute('/flags');
    flags.value = data.value ? data.value : ({} as FeatureFlags);

    return flags.value
  }

  return {
    fetch
    flags
  };
};
```

And then, in the component use it like following:

```vue
<script setup lang="ts">
const { flags, fetch } = useFeatureFlags();

onMounted(async () => {
  await fetch('/flags');
});
</script>

<template>
  <AwesomeFeature v-if="flags.awesome_feature" />
</template>
```

The first approach requires developer to do less steps but also gives him less control over how these flags are fetched. I personally prefer this approach as I am lazy and if I can have similar effect with less steps, I will choose this approach :D

## Bonus

To not stress your backend/middleware or the third party service with too many requests for flags (and taking into account that these flags have a tendency to not change that often) you can implement a caching solution along with a timeout that will send a request for flags at most once per five minutes.

## Summary

Nicely done! You have just learned how to build a custom Vue composable to handle feature flags. You understand that there are (at least) three approaches in how these flags can be managed and two approaches in how these flags can be used in the code. Hope this will help you manage your feature flags and have safe release process.

Take care and see you next time!