Feature Toggle Client
Changelog
- 0.6.0
- Library now supports only CommonJS modules, not possible to use it with
script
tag - Using URL instead of
isProd
toggle in configuration
- Library now supports only CommonJS modules, not possible to use it with
- 0.5.1
- Fixing issues with lambda
- 0.5.0
- Recalculation of the toggles is done automatically now (again) with possibility to make it manual also.
- No need to put URL in the configuration anymore.
- Toggle is recalculated after distribution value is changed on server.
- 0.4.1
- Implemented the library so that it can be loaded with script tag
- 0.4.0
- Removed authentication when calling API
- 0.3.0
- Execution of toggle calculation is now manual step. UMD and webpack added
- 0.2.0
- Added browser Adapter and necessary refactoring for this
- 0.1.1
- Removed dependencies on fp-ts, refactored the interfaces
- 0.1.0
- First release done in fp-ts
What is it
Feature Toggle is a technique that allows you to change application behavior dynamically, without changing and re-deploying the code. It's based on wrapping the features with code branches (usually with if
statements) where conditions are decided based on a state provided by Feature Toggle Server. Those conditions can be also determined by rolling the dice and allowing you to release new features just to a fraction of the user base.
Besides that, it is one of the ways to achieve Continuous Deployment in a safe way, testing new features on production. With partial releases, it helps developers to see the performance impact of the new feature without writing performance tests.
Installation
You can install it with npm with this command:
npm install @u2dv/feature-toggle-client
How do I use it
Feature Toggle Client automates this process for developers by fetching the state of the toggles from the server, deciding which user will have a particular feature turned on, keeping the track of that state through cookies and allowing users to force toggles on.
Here is the example how it could be used:
import { featureTogglesClient, FeatureTogglesConfig } from 'feature-toggle-client';
const config: FeatureTogglesConfig = { /*...*/ };
const client = await featureTogglesClient('new-feature', 'test-feature')(config);
if (client.isOn('new-feature')) {
//here comes the new feature
} else {
//here comes the old code if needed
}
When you are calling featureTogglesClient
, you have to specify in which toggles are you interested and also configuration for the Feature Toggle Client (see the section below). Once the client is instantiated, the values for feature toggles are fetched from server and calculated. After that you can access use them for code branching.
NOTE: Getting state from toggle that was not specified in the list of toggles in featureTogglesClient
call will always return false
to be on the safe side. Make sure you don't have typos, so best way is to make this typesafe for example type FeatureToggles = 'Toggle-1' | 'Toggle-2';
and use type FeatureToggles
instead of string.
After library is initialised, it will take care of fetching the toggle states from servers, enabling feature for just a fraction of users and saving the states of the toggles to the client storage.
You can also use this library for testing new features in production environemnt. If you turn off the feature for all customers and override it in your browser with query parameters or headers, only you will be able to see this feature. To override the feature you can add uptodate-toggles
query parameter and put features you want to turn on (uptodate-toggles=feature1,feature2
) or you can do the same with a X-uptodate-toggles
header.
Configuration
This is how configuration might look like:
import { FeatureTogglesConfig, apiGatewayAdapter } from 'feature-toggle-client';
const config: FeatureTogglesConfig = {
serverURL: 'https://feature-toggle-server.com',
adapter: apiGatewayAdapter(event),
refreshInterval: 60 * 1000,
failToStateOff: true,
};
- serverURL: The URL of the feature toggle server
- adapter: Helper that translates HTTP request data from environment to format suitable for Feature Toggle Client. See the Adapters section
- refreshInterval: Optional. How often (in milliseconds) the Feature Toggle API will be called to fetch results. If omitted API will be called only once (useful for Lambda functions)
- failToStateOff: If it is set to true and Feature Toggle Server is offline, feature toggles will be in state off. If it is set to false, it will throw exception
Adapters
Adapters are helpers that are allowing Feature Toggle Client to be used with different frameworks and environments. As Feature Toggle Client is relying on request data (headers and query parameters), adapters are necessary for integrating it to any project.
To create a new Adapter, extend the Adapter
interface, where three things needs to be implemented:
- forced: it should contain toggles that were fetched from the request data and have purpose to overwrite values of the feature toggles.
- saved: it should contain toggles that were saved somewhere (cookies, storage) in previous requests and it is in same format as they were saved in save function (below)
- save: this is a function that takes feature toggles and saves it in some storage (i.e. cookies)
The following adapters are available:
APIGateway
Intended usage would be in Lambda that is connected to the APIGateway. It expects API Gateway event as an input to generate the Adapter object.
WARNING: Because APIGateway+Lambda combination is setting cookies by specifying Set-Cookies
header in Lambda, this adapter is not automatically saving the states of feature toggles in cookies automatically. It is left to developers to implement this important feature.
Example of the usage:
import { FeatureTogglesConfig, apiGatewayAdapter } from 'feature-toggle-client';
const handler = (event) => {
const config: FeatureTogglesConfig = {
// ...
adapter: apiGatewayAdapter(event),
// ...
};
};
Browser
Intended to be used on the frontend in any browser. It expects parameters on where to find the current browser URL, Cookie and function that describes how to save the Cookie. Check the code below for example:
import { FeatureTogglesConfig, browserAdapter } from 'feature-toggle-client';
const config: FeatureTogglesConfig = {
// ...
adapter: browserAdapter(document.location, document.cookie, (str: string) => { document.cookie = str }),
// ...
};
How to release a new version
Before publishing the new version, it would be good that you test the library first. You can do that by running:
npm pack
which will create package. You can install this package by referencing the path of the file when you're installing the library
npm install <path-to-the-package>
Once you decide that you're finish with the featuresets for the new version, you have to create commit that will mark the release of the new version. In that commit you should change version in package.json and Changelog section of this document to reflect the changes there. Be aware of how semantic versioning is working when you're determining what version value you should use.
After you push the commit, you have to manually run Release
step in Bitbucket Pipelines. This will check that version don't already exist and create git tag (and therefore release).