npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

ember-cli-conditional-compile

v2.0.0

Published

Conditional compilation (feature-flags) for Ember apps

Downloads

314

Readme

ember-cli-conditional-compile

Build Status

The goal of ember-cli-conditional-compile is to provide easy to use feature switches to Ember applications such that code that is hidden behind a disabled feature switch is not in the compiled code.

Getting Started

This is an ember-cli addon, so all you need to do is

    ember install ember-cli-conditional-compile

Compatibility

Version 2.x targets Ember 3.x and beyond. It is tested against the latest ember release and the latest beta release (See config/ember-try.js for the testing matrix)

Upgrading to 2.x

Our workaround around a broccoli pipeline bug in newer versions of ember-cli slightly changes the semantics of includeDirByFlag. Instead of a RegExp, you now need to specify a Glob-style pattern.

Usage

To actually use the feature switches you'll need to add some configuration in your environment.js file. For example, lets pretend you want to have two feature switches; ENABLE_FOO and ENABLE_BAR:

var ENV = {
  // other settings ...

  featureFlags: {
    ENABLE_FOO: true,
    ENABLE_BAR: true,
  },
  includeDirByFlag: {
    ENABLE_FOO: ["pods/foos/**", "pods/foo/**"],
    ENABLE_BAR: [],
  },
};

// other environments ...

if (environment === "production") {
  ENV.featureFlags.ENABLE_FOO = false;
}

Alternatively, you can define your feature flags in config/feature-flags.js looking like this:

module.exports = function (environment) {
  const GLOBAL_FLAGS = {
    featureFlags: {
      ENABLE_FOO: true,
      ENABLE_BAR: true,
    },
    includeDirByFlag: {
      ENABLE_FOO: [/pods\/foos/, /pods\/foo/],
      ENABLE_BAR: [],
    },
  };

  if (environment === "production") {
    GLOBAL_FLAGS.featureFlags.ENABLE_FOO = false;
  }

  return GLOBAL_FLAGS;
};

This has two advantages: It declutters environment.js a bit, especially if you have many flags, but also prevents your flag names from leaking into the application code under certain circumstances.

We'll look at the two new options in more detail below, but for now we can see that by default both features are enabled, but in the production environment ENABLE_FOO is disabled, and related code under the pods/foos and pods/foo directories are excluded from compilation.

ENV.featureFlags

This setting sets up which flags will be available to actually switch use. A value of true means that the flag will be enabled, false means that it will not be.

ENV.includeDirByFlag

Given a key which has been defined above, the value is an array of regexes of files/paths which will only be included in the compiled product if the related feature flag is enabled. In the example above, in the development environment ENABLE_FOO is true, so the pods/foo and pods/foos paths will be included.

However, since the flag is false in production, any code in those directories will not be compiled in.

How it works

ember-cli-conditional-compile adds itself to the Broccoli compile pipeline for your Ember application. Depending on which environment you're building it acts in two different ways:

Development and test environments

Global variables are injected into the page which have the current state of the feature flags. For example:

if (ENABLE_FOO) {
  this.route("foo");
  console.log("The feature ENABLE_FOO is enabled in this environment");
}

will be represented in development and test environments as:

window.ENABLE_FOO = true;

if (ENABLE_FOO) {
  this.route("foo");
  console.log("The feature ENABLE_FOO is enabled in this environment");
}

In Handlebars/HTMLBars templates, you can also make use of the flags using the if-flag block helper:

{{#if-flag ENABLE_FOO}}
  <p>Foo is enabled! \o/</p>
{{else}}
  <p>Foo is disabled</p>
{{/if-flag}}

You can also use the unless-flag style block helper:

{{#unless-flag ENABLE_FOO}}
  <p>Foo is disabled</p>
{{else}}
  <p>Foo is enabled! \o/</p>
{{/unless-flag}}

Production environment

We use UglifyJS's global_defs feature to replace the value of feature flags with their constant values. UglifyJS's dead code implementation then cleans up unreachable code and performs inlining, such that:

if (ENABLE_FOO) {
  this.route("foo");
  console.log("The feature ENABLE_FOO is enabled in this environment");
}

will be represented in the production environment as the following if ENABLE_FOO is configured to be true:

this.route("foo");
console.log("The feature ENABLE_FOO is enabled in this environment");

or the following if ENABLE_FOO is configured to be false;

// empty since the condition can never be satisfied!

Furthermore, if you use the HTMLBars helpers the AST transformations will shake out and remove impossible-to-reach sides of the condition:

{{#if-flag ENABLE_FOO}}
  <p>Foo is enabled</p>
{{else}}
  <p>This won't be reached, because ENABLE_FOO is true</p>
{{/if-flag}}

will get transformed into:

<p>Foo is enabled</p>

This is really handy, since it vastly cuts down on the amount of precompiled template code that your users need to download even though it'll never be executed!

Defining additional environments

By defining ENV.featureFlagsEnvironment you can separate your feature flags by more than just test/development/production, for example to have a beta environment that is identical to production but has a couple more flags activated. This only works if you have your flags in config.featureFlags - The environment passed in into the wrapper function will be ENV.featureFlagsEnvironment if set.

Licence

This library is lovingly brought to you by the FreshBooks developers. We've released it under the MIT license.