Security News
JSR Working Group Kicks Off with Ambitious Roadmap and Plans for Open Governance
At its inaugural meeting, the JSR Working Group outlined plans for an open governance model and a roadmap to enhance JavaScript package management.
Feature toggles and A/B tests are wonderful, but can easily introduce debt in your codebase.
This project allows you to experiment and automatically clean up your JavaScript experimentation code after the experiment concludes using JSCodeShift codemods.
The library consists of two related concepts:
At the heart of our experimentation framework is the toggle
function.
A toggle allows you to switch between multiple experiment variants (a/b/c/...) and also turn functionality on or off (feature flags)
It can be used in a variety of ways:
We use React at vio.com and some of the code examples use JSX, but the code and concept is compatible with any front-end framework or architecture.
The main reason for using the Opticks library is to be able to clean your code afterwards by providing a predictable experimentation API.
We don't intend to reinvent the wheel and aim to keep it easy to integrate existing frameworks and services such as Optimizely, LaunchDarkly and Conductrics behind a simple facade.
Currently Opticks has two 'integrations' or adapters, a simple one based on a local key/value store, and one wrapping the Optimizely Full Stack SDK. Once initialized, using/consuming the toggle decisions is the same.
In the future the integrations will be packaged separately so you can include
the one you need, for now the "simple" is the default and the Optimizely adapter
can be included directly via:
import Opticks from 'opticks/lib/optimizely'
See the Simple integration documentation.
See the Optimizely integration documentation.
Toggles can be used to implement a/b/c style MVT testing and on/off feature flags as well.
We specify multiple variants of which only one is active at any time.
By convention the variants are named a
(control), b
, c
etc.
While it's recommended to use the strategy described in executing code for variants, the following shows how the variant executing and code clean up works under the hood.
The simplest signature is as follows, to read the toggle value directly:
toggle(experimentId: string) => { variant: 'a' | 'b' | 'c' | 'd' | ... }
For example when the user is assigned to the b
side:
const fooResult = toggle('foo')
if (fooResult === 'b') console.log('b side of the foo experiment')
This works fine, but will result in code that will be hard to clean up
automatically. Considering the codemods replace the toggle with the 'winning'
value (b
in this case):
const fooResult = 'b'
if (fooResult === 'b') console.log('b variant of the foo experiment')
This would leave your code more messy than necessary. You could skip the intermediate value but it will still result in awkward leftover code:
if (toggle('foo') === 'b') ...
// becomes
if ('b' === 'b') ...
// or
if ('a' === 'b') ...
Rather than reading the return value directly, you can map your variant to arguments to the toggle function, like so:
// Defines the result if that toggle or experiment wins, either a function that
// will be executed, or any other value
type ToggleResultType = function | any
// do something for a/b/c variant:
toggle(
experimentId,
variantA: ToggleResultType,
variantB: ToggleResultType,
?variantC: ToggleResultType,
...
)
The signature might look more complicated, but it allows you to define what the
results for your variants a, b, c etc map to. The first value is the
experimentId, then the values for a
, b
, etc.
For instance:
// simple boolean switch
const shouldDoSomething = toggle('foo', false, true)
// multiple variants as strings
// 'black' is the default, red and green are variants to experiment with
const buttonColor = toggle('foo', 'black', 'green', 'red')
The benefit is that after concluding your experiment, you can integrate the
winning variation's code directly without awkward references to a
or b
etc.
After you run the codemods to declare b
the winner, the corresponding raw
value is kept:
const shouldDoSomething = toggle('foo', false, true)
const buttonColor = toggle('foo', 'black', 'green', 'red')
// becomes:
const shouldDoSomething = true
const buttonColor = 'green'
Much better already, but there is more room for improvement, especially if you want to do things conditionally for a variant.
Consider the following set up:
const shouldShowWarning = toggle('shouldShowWarning', false, true)
if (shouldShowWarning) showWarning()
// or directly:
if (toggle('shouldShowWarning', false, true)) showWarning()
This would end up with an orphaned conditional after the codemods did their cleaning:
const shouldShowWarning = true
if (shouldShowWarning) showWarning()
// or directly
if (true) showWarning()
The next section explains a more useful concept for this type of conditional branching.
A better approach that allows you to clean the code easier would be to encapsulate variant logic by executing code from the toggle:
const price = 100
const savings = 20
const CTA = toggle(
'CTAWording',
() => `Buy now for just ${price}` // variant a (default)
() => `Buy now for ${price} and save ${savings}`, // variant b
() => `From ${price + savings} to ${price}` // variant c
)
Then after running the cleaning codemods when the b
variant wins:
const price = 100
const savings = 20
const CTA = `Buy now for ${price} and save ${savings}`
Or for an example of conditionally calling code:
alwaysDoSomething()
toggle('shouldShowWarning', null, () => shouldShowWarning())
This shows two special concepts of the codemods, passing a null
and the use of
arrow functions.
Passing null
allows for full clean up when that branch loses.
For winners, the body of the arrow function is kept as-is.
After running the codemods with the winning b
variant:
alwaysDoSomething()
shouldShowWarning() // no trace this was the result of a winning experiment
But if a
would have won:
alwaysDoSomething()
// no trace that something was experimented with but lost
Above are just a few examples of how the codemods operate on the code. For instructions and more recipes, see Removal of dead code.
FAQs
FindHotel Toggle Flag JavaScript SDK
The npm package opticks receives a total of 444 weekly downloads. As such, opticks popularity was classified as not popular.
We found that opticks demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 9 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
At its inaugural meeting, the JSR Working Group outlined plans for an open governance model and a roadmap to enhance JavaScript package management.
Security News
Research
An advanced npm supply chain attack is leveraging Ethereum smart contracts for decentralized, persistent malware control, evading traditional defenses.
Security News
Research
Attackers are impersonating Sindre Sorhus on npm with a fake 'chalk-node' package containing a malicious backdoor to compromise developers' projects.