Closed marcins closed 1 month ago
Any thoughts about how we'll manage the lifecycle of feature flags? AFAIK there's no perfect solution to the problem of feature flag atrophy but it's nice to at least consider the problem up front.
Seems like a solid proposal to me 👍
Any thoughts about how we'll manage the lifecycle of feature flags? AFAIK there's no perfect solution to the problem of feature flag atrophy but it's nice to at least consider the problem up front.
Fair point. There's definitely a risk that we might end up with features behind a flag that for whatever reason don't "graduate" to real features for a long time. I suppose it's one of those things that we'll need to address as it comes up.
We've kind of already got this to some extent with some of the unstable_
features we added during our long migration. The main one I can think of is the "async runtime" stuff. Whether that was behind a feature flag or unstable_
prefix it's still just sitting there with no current plan for what needs to be done to "graduate" it.
💬 RFC
We have a lot of complex features / pieces of work planned for Parcel over the foreseeable future. In order to be able to meet our goals of: being able to work on features in parallel, deliver value incrementally, and provide the ability to dogfood new / risky / complex features at scale before making them generally available, we need to shift the approach to how we do feature development and releases in Parcel.
The summary of this proposal is:
v2
) branch - this means we can "immediately" (once a build runs) consume a release rather than waiting for a nightly to run.Trunk based development
The main philosophy shift here is that rather than working on a feature on a branch until it is done / tested / ready for release, features are able to be released piecemeal onto the main branch and are protected by feature flags (see below for feature flags description).
This means that where changes are isolated in scope within a module, they are conditionally executed based on feature flag outcomes. Where changes are more broad and would require peppering conditionals throughout the code then a parallel implementation needs to be created and conditionally included / abstracted at a higher level. How this is achieved will be specific to particular use cases so is not prescribed by this RFC.
(Open question - what about changes that require new dependencies? Are there any issues with this? This doesn't apply to dependency bumps, those would not be possible to feature flag easily)
The advantages of this approach are that integration costs are lower - you're not needing to constantly keep a branch in sync with what's happening on the main branch. Parallel work from a baseline piece of work on the main branch is easier to achieve.
The disadvantage is additional overhead for complex changes of maintaining an abstraction or conditional code.
We believe the advantages for parallelising work and shipping changes sooner for internal usage outweigh the disadvantages.
Feature flags
We will introduce the concept of feature flags in Parcel. This will allow us to ship inert code in open source, that we are actively testing and stabilising in our internal large scale use cases. Without the ability to do this, in combination with the improvements to the development model above, it may become untenable for us to work in the open source repository as the source of truth.
Note for the purposes of this proposal feature flags will not be used to produce different binary output from Rust builds - at this stage if some new Rust feature is being developed that has a dependency on a new crate, that crate will need to be included in the build even if unused.
The main approach to feature flagging is largely inspired by other open source projects that take this approach such as React (https://legacy.reactjs.org/docs/how-to-contribute.html#feature-flags) and Relay (https://github.com/facebook/relay/blob/main/packages/relay-runtime/util/RelayFeatureFlags.js, https://github.com/facebook/relay/blob/main/compiler/crates/common/src/feature_flags.rs)
The proposed approach is:
ParcelOptions
on the JavaScript side..parcelrc
- with their defaults being set in@parcel/config-default
, with a new top levelfeatureFlags
key.There is a spike implementation here: https://github.com/parcel-bundler/parcel/compare/v2...spike-feature-flags
The main considerations when trying out the spike:
ParcelOptions
/PluginOptions
- with support for defaults in config, with overrides inInitialParcelOptions
- is relatively straightforward though has to be done in a few places to ensure types flow properly.transform
this currently receives it's options as an untypedJsObject
.--feature-flag
.. e.g.parcel build --feature-flag myFeature=true --feature-flag someOtherFeature=false
. The feature flag definitions are in an object exported from@parcel/feature-flags
and can be validated that they exist in the CLI via a custom option processing function.Next steps