Reimagine how the babel transform works #53
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This PR is part of #36. It is a reimagining of the babel transform that is used to convert the
variation
JS helper in to code that references the launch darkly service. This new approach somewhat simplifies the transform and also the reasoning on how it works.Historical context
The original babel transform largely worked fine, however, it always had one lingering flaw, and that was it was tricky to detect when a
variation
helper was used inside a computed property. The reason we want to do this is so that we can auto insert the feature flags as dependent keys on the computed so that it will recalculate if the feature flag values change. As an example, the babel transform should take this:and convert it to this:
The reason this was tricky was that, because of how babel transforms are run, in a non deterministic order, it's very hard to be able to know what state the code will be in when this transform is running. For instance, firstly, depending on what version of Ember is being used, has the user imported
computed
from the old module import shims (ember-computed
) or from the new ones (@ember/object
)? Secondly, is the code still using the import or has the transform to transpile it in toEmber.computed
run already?Basically, depending on which version of Ember was used, and depending on how lucky you were when the transform ran, sometimes it would add the keys, sometimes it wouldn't.
So, we needed to find a more easy to reason about approach to signalling that a
variation
helper was used inside a computed property.This is the main goal of this PR. The secondary goal is to simplify the transform to make it easier to understand what is going on.
New approach
The new approach as somewhat sacrificed the developer aesthetic of magically inserting the CP dependent keys but has drastically increased the reliability of the transform, increased the confidence we have of shipping it and removed ambiguity around which version of Ember is being used.
The new approach has introduced a second export,
computedWithVariation
. Having this explicit export allows us to signal to the transform that we need to add the dependent keys and we can be pretty sure that no other transform has modified this part of the code before us.The intention is that users will use this instead of the regular
computed
provided by Ember, when they want to use a variation inside a computed property and have the dependent keys automatically added. This sounds like a lot of mental overhead but in reality it's very little. Here's why...If the user doesn't care about recomputing the CP when a flag changes then there is no need to think about
computedWithVariation
. From a production perspective, users would only care about this if they have marked a flag as a "streaming" flag. However, from a development perspective, it is useful for flag changes to take effect when enabling/disabling them from the JS console. Still, it's not needed if the user doesn't care about this.If the user does want their CP to be recomputed then they can simply alias
computedWithVariation
ascomputed
and use it anywhere in the file that they'd use the Ember provided computed. This is becausecomputedWithVariation
is simply a re-export ofcomputed
from@ember/object
. We just need it to signal to the transpiler that we should be looking forvariation
calls inside it and adding the flags as dependent keys.So, users can simply do this:
and they can use computed as they normally would. If they remove feature flags from that code then it's simply a matter of replacing that import with the standard
@ember/object
import. Even if they forget it won't matter.Another bonus that this PR adds is messaging to the user if they don't include the babel plugin but do reference the
variation
helper. Before this PR,variation
was a "fake" import that was replaced by the launch darkly service code. This meant that if the user did not include the babel transform then the code would not compile because it couldn't find avariation
import fromember-launch-darkly
. However, this PR now adds avariation
export that simply throws an error with some useful messaging for the user pointing them to the docs. This will only fire if the user has referenced thevariation
helper and not included the babel transform.Caveats with babel transform
Even with the new transform, there are a couple of caveats whereby the
variation
helper doesn't work. These are now covered in the README so users can be aware.In short, the
variation
helper won't work when used in objects that don't have anowner
(as we need to get access to the injectedlaunchDarkly
service), it won't work in native classes and we don't, yet, supply an@computedWithVariation
decorator.